|
using System; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Text.Json; |
|
using System.Xml; |
|
using System.Xml.Serialization; |
|
|
|
public class Program |
|
{ |
|
public static void Main() |
|
{ |
|
// Serialize a array as element text using XmlTextAttribute |
|
// e.g.: <root>1 2 3</root> |
|
|
|
// FAIL: |
|
// serialization: missing whitespace separators: <Root1>123</Root1> |
|
// deserialization: doesn't split on whitespace and |
|
XmlElement(); |
|
|
|
// OK: shadow property does splitting and joining |
|
ShadowProperty(); |
|
|
|
// OK: alternative using attribute: <Root2 Ids="1 2 3" /> |
|
XmlAttribute(); |
|
} |
|
|
|
public static void XmlElement() |
|
{ |
|
Console.WriteLine("Root1 string[] property with XmlTextAttribute"); |
|
var ser = new XmlSerializer(typeof(Root1)); |
|
var sb = new StringBuilder(); |
|
var writer = XmlWriter.Create(sb, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }); |
|
|
|
ser.Serialize(writer, new Root1 { Ids = ["1", "2", "3"] }, new XmlSerializerNamespaces([new XmlQualifiedName("", "")])); |
|
Console.WriteLine($"[FAIL] serialize is missing whitespace separators: {sb}"); |
|
// expected: <Root1>1 2 3</Root1> |
|
// actual: <Root1>123</Root1> |
|
|
|
Root1 root1 = (Root1)ser.Deserialize(new StringReader("<Root1>1 2 3</Root1>"))!; |
|
Console.WriteLine($"[FAIL] deserialize returns only 1 squashed element instead of 3 separated: {JsonSerializer.Serialize(root1.Ids)}\n"); |
|
// expected: 3 elements: ["1", "2", "3"] |
|
// actual: 1 element: "1 2 3" |
|
} |
|
|
|
public static void ShadowProperty() |
|
{ |
|
Console.WriteLine("Root2 workaround with shadow property for splitting and joining:"); |
|
var ser = new XmlSerializer(typeof(Root2)); |
|
var sb = new StringBuilder(); |
|
var writer = XmlWriter.Create(sb, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }); |
|
|
|
ser.Serialize(writer, new Root2 { Ids = [1, 2, 3] }, new XmlSerializerNamespaces([new XmlQualifiedName("", "")])); |
|
Console.WriteLine($"[OK] Root2 serialize as whitespace separated list: {sb}"); |
|
// expected: <Root2>1 2 3</Root2> |
|
// actual: correct |
|
|
|
// Deserialization |
|
var xml = "<Root2>1 2 3</Root2>"; |
|
var stream = new StringReader(xml); |
|
var root2 = ser.Deserialize(stream) as Root2; |
|
Console.WriteLine($"[OK] Root2 deserialize has 3 elements: {JsonSerializer.Serialize(root2.Ids)}\n"); |
|
// expected: 3 elements |
|
// actual: correct |
|
} |
|
|
|
public static void XmlAttribute() |
|
{ |
|
Console.WriteLine("Root3 alternative serialization using xml attribute:"); |
|
var ser = new XmlSerializer(typeof(Root3)); |
|
var sb = new StringBuilder(); |
|
var writer = XmlWriter.Create(sb, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }); |
|
|
|
ser.Serialize(writer, new Root3 { Ids = ["1", "2", "3"] }, new XmlSerializerNamespaces([new XmlQualifiedName("", "")])); |
|
Console.WriteLine($"[OK] serialize: {sb}"); |
|
// expected : attribute Ids="1 2 3" |
|
// actual: correct |
|
|
|
var root3 = ser.Deserialize(new StringReader("""<Root3 Ids="1 2 3" />""")) as Root3; |
|
Console.WriteLine($"[OK] deserialize: {JsonSerializer.Serialize(root3.Ids)}\n"); |
|
// expected: 3 elements |
|
// actual: correct |
|
} |
|
} |
|
|
|
public class Root1 |
|
{ |
|
// The XmlTextAttribute [with type set to string] informs the XmlSerializer that strings should be serialize as XML [inner]text. |
|
// Unfortunately, array on elements are not supported: |
|
// .NET Framework https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/t84dzyst(v=vs.100) "The .NET Framework provides accurate bindings for XML attribute declarations with list types, **but not for element declarations**." |
|
// .NET https://learn.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmltextattribute |
|
[XmlText] |
|
public string[] Ids; |
|
} |
|
|
|
public partial class Root2 |
|
{ |
|
[XmlText] |
|
public string Value; |
|
} |
|
|
|
public partial class Root2 |
|
{ |
|
[XmlIgnore] |
|
public int[] Ids |
|
{ |
|
get => Value.Split(" ").Where(v => !string.IsNullOrWhiteSpace(v)).Select(int.Parse).ToArray(); |
|
set => Value = string.Join(" ", value); |
|
} |
|
} |
|
|
|
public class Root3 |
|
{ |
|
[XmlAttribute] |
|
public string[] Ids; |
|
} |