Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public static IDecorator<IList<XmlConverter>> AddEnumerableConverter(this IDecor
{
if (isDictionaryLike)
{
w.WriteStartElement(q.LocalName);
w.WriteStartElement(q.Prefix, q.LocalName, q.Namespace);
foreach (var element in o)
{
var elementType = element.GetType();
Expand All @@ -125,31 +125,38 @@ public static IDecorator<IList<XmlConverter>> AddEnumerableConverter(this IDecor
var keyName = Decorator.Enclose(keyValue.ToString()).SanitizeXmlElementName();
if (Decorator.Enclose(valuePropertyType).IsComplex())
{
Decorator.Enclose(w).WriteObject(valueValue, valuePropertyType, opts => opts.Settings.RootName = new XmlQualifiedEntity(keyName));
Decorator.Enclose(w).WriteObject(valueValue, valuePropertyType, opts => opts.Settings.RootName = new XmlQualifiedEntity(keyName, q.Namespace));
}
else
{
w.WriteElementString(keyName, Convert.ToString(valueValue, CultureInfo.InvariantCulture));
w.WriteStartElement(keyName, q.Namespace);
w.WriteValue(valueValue);
w.WriteEndElement();
}
}
w.WriteEndElement();
}
else
{
var isDocumentRoot = w.WriteState == WriteState.Start;
if (isDocumentRoot) { w.WriteStartElement(q.Prefix, q.LocalName, q.Namespace); }
var qe = new XmlQualifiedEntity(q.Prefix, q.LocalName, q.Namespace);
foreach (var item in o)
{
if (item == null) { continue; }
var itemType = item.GetType();
if (Decorator.Enclose(itemType).IsComplex())
{
var localName = q.LocalName;
Decorator.Enclose(w).WriteObject(item, itemType, opts => opts.Settings.RootName = new XmlQualifiedEntity(localName));
Decorator.Enclose(w).WriteObject(item, itemType, opts => opts.Settings.RootName = qe);
}
else
{
w.WriteElementString(q.LocalName, Convert.ToString(item, CultureInfo.InvariantCulture));
w.WriteStartElement(q.Prefix, q.LocalName, q.Namespace);
w.WriteValue(item);
w.WriteEndElement();
}
}
if (isDocumentRoot) { w.WriteEndElement(); }
Comment on lines +141 to +159

Copilot AI Feb 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updated flatten-items writer logic (namespace/prefix propagation, WriteValue formatting, and document-root wrapping) is not currently covered by unit tests. Please add tests that exercise: (1) FlattenCollectionItems=true with a root IEnumerable where Settings.RootName is set (ensuring the output is well-formed XML with a single document element), (2) primitive formatting (e.g., bool emits "true/false"), and (3) namespace/prefix preservation on the emitted elements.

Copilot uses AI. Check for mistakes.
}
}
else
Expand Down
11 changes: 8 additions & 3 deletions src/Cuemon.Xml/Serialization/Formatters/XmlFormatterOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,14 @@ internal XmlSerializerOptions RefreshWithConverterDependencies()
_refreshed = true;
if (Settings.FlattenCollectionItems)
{
var existing = Decorator.Enclose(Settings.Converters).FirstOrDefaultWriterConverter(typeof(IEnumerable));
if (existing != null) { Settings.Converters.Remove(existing); }
Decorator.Enclose(Settings.Converters).AddEnumerableConverter(flattenItems: true);
var converters = Decorator.Enclose(Settings.Converters);
while (true)
{
var existing = converters.FirstOrDefaultWriterConverter(typeof(IEnumerable));
if (existing == null) { break; }
Settings.Converters.Remove(existing);
}
converters.AddEnumerableConverter(flattenItems: true);
Comment on lines +132 to +139

Copilot AI Feb 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RefreshWithConverterDependencies now removes all writer converters that can convert IEnumerable before inserting the flattened enumerable converter. Please add a unit test that registers multiple IEnumerable-capable converters ahead of the default one and verifies that when FlattenCollectionItems=true, serialization actually uses the flattened converter (and that all prior IEnumerable writer converters are removed as intended).

Copilot uses AI. Check for mistakes.
}
Decorator.Enclose(Settings.Converters)
.AddExceptionConverter(SensitivityDetails.HasFlag(FaultSensitivityDetails.StackTrace), SensitivityDetails.HasFlag(FaultSensitivityDetails.Data))
Expand Down
Loading