Monica
Monica
CC#
Created by Monica on 11/28/2022 in #help
❔ XML serialization woes
I'm trying to use XmlSerializer, and for some reason I can't get it to serialize an array of child elements. If I specify the name manually (in the XmlElementAttribute) it works fine, but I already specify the element name on the target type using XmlTypeAttribute. My types look something like this:
public abstract record XmlGrammarItem(
[property: XmlAttribute("Name")]
string Name,
[property: XmlAttribute("Base")]
string? Base,
[property: XmlAttribute("Type")]
string? Type);

[XmlType("Node")]
public sealed record NodeGrammarItem(string Name, string? Base,
[property: XmlElement]
XmlNodeMember[] Members)
: XmlGrammarItem(Name, Base, Name)
{
public NodeGrammarItem() : this(null!, null, null!) {}
}

[XmlType("Member")]
public sealed record XmlNodeMember(
[property: XmlAttribute("Name")]
string Name,
[property: XmlAttribute("Type")]
string Type,
[property: XmlAttribute("Optional")]
bool Optional,
[property: XmlElement]
XmlMemberValue[] Values)
{
public XmlNodeMember() : this(null!, null!, false, null!) {}
}

[XmlType("Value")]
public sealed record XmlMemberValue(
[property: XmlAttribute("Type")]
string Type)
{
public XmlMemberValue() : this((string)null!) {}
}
public abstract record XmlGrammarItem(
[property: XmlAttribute("Name")]
string Name,
[property: XmlAttribute("Base")]
string? Base,
[property: XmlAttribute("Type")]
string? Type);

[XmlType("Node")]
public sealed record NodeGrammarItem(string Name, string? Base,
[property: XmlElement]
XmlNodeMember[] Members)
: XmlGrammarItem(Name, Base, Name)
{
public NodeGrammarItem() : this(null!, null, null!) {}
}

[XmlType("Member")]
public sealed record XmlNodeMember(
[property: XmlAttribute("Name")]
string Name,
[property: XmlAttribute("Type")]
string Type,
[property: XmlAttribute("Optional")]
bool Optional,
[property: XmlElement]
XmlMemberValue[] Values)
{
public XmlNodeMember() : this(null!, null!, false, null!) {}
}

[XmlType("Value")]
public sealed record XmlMemberValue(
[property: XmlAttribute("Type")]
string Type)
{
public XmlMemberValue() : this((string)null!) {}
}
And the XML I'm trying to (de)serialize looks like this:
<Node Name="CompilationUnitSyntax">
<Member Name="Contents" Type="StatementListSyntax" />
<Member Name="EndOfFile" Type="EndOfFileTokenSyntax" />
</Node>
<Node Name="CompilationUnitSyntax">
<Member Name="Contents" Type="StatementListSyntax" />
<Member Name="EndOfFile" Type="EndOfFileTokenSyntax" />
</Node>
To validate that the serialization works, I'm currently doing this:
var serializer = new XmlSerializer(typeof(NodeGrammarItem));
var obj = (NodeGrammarItem)serializer.Deserialize(File.OpenRead("node.xml"))!;
serializer.Serialize(Console.Out, obj);
var serializer = new XmlSerializer(typeof(NodeGrammarItem));
var obj = (NodeGrammarItem)serializer.Deserialize(File.OpenRead("node.xml"))!;
serializer.Serialize(Console.Out, obj);
Is there something I'm missing in order to allow XmlSerializer to read the XmlTypeAttribute for these types, or do I have to specify the element name using XmlElementAttribute? I've not been able to find anything on the docs that would suggest otherwise.
2 replies