I am working on a deserializer in C# for an XML file type for a program I don't have any control over. Unfortunately, the XML file structure completely breaks conventions in two major ways, as far as I can tell, and it's been complicating the patterns for me.
The file is used to define user interface components within a video game. There is a main XML element called "layout" that is always the root element, with two child elements - <hierarchy> and <components>.
<layout
version="137"
comment="Agh!">
<hierarchy>
<!-- see below -->
</hierarchy>
<components>
<!-- see below -->
</components>
</layout>
The hierarchy element contains the hierarchical structure of the UI tree defined by each layout file. It always starts with a single "root" node, and the root node can have a single child, but beneath that any node can have as many children as needed.
<hierarchy>
<root this="1234">
<main_child this="5678">
<child_a/>
<child_b/>
<child_c>
<grandchild_a/>
</child_c>
</main_child>
</root>
</hierarchy>
And the components hierarchy has a similar strange structure, with every child of the "components" node being one of two very similar types, but the actual tag of each node can vary as above.
<components>
<root this="1234" id="root">
<!-- etc... -->
</root>
<main_child
this="5678"
id="main_child"
state="active">
</main_child>
<!-- and so on, with one "primary" node for each UI component in this file -->
</components>
These make it difficult to quickly parse the child elements of both and , and I'm having trouble getting XmlSerializer to recognize any of the children for both of these sections. I can get "root" to be recognized by the hierarchy class easily, but getting that to work recursively hasn't worked yet, and I'm having difficulty getting the array beneath to work also.
Originally, I was developing a manual converter using XDocument, but that showed to be significantly too-much work since it required unique handling of every single attribute, of which there are hundreds in this file, which can also change between "versions" of it.
I've been testing these out through using the various Xml attributes available as hinters for the XmlSerializer.
public class LayoutModel {
[XmlAttribute("version")]
public uint Version { get; set; }
// etc ...
[XmlElement("hierarchy")]
public HierarchyModel Hierarchy { get; set; }
[XmlElement("components"), typeof(ComponentModel))]
public ComponentModel[] Components { get; set; }
}
public class HierarchyModel {
// This converts fine, but getting the understanding of the children is not working.
[XmlElement("root")]
public HierarchyNodeModel RootNode { get; set; }
}
public class HierarchyNodeModel {
[XmlArrayItem(Type = typeof(TestHierarchyNodeModel))]
[XmlArray]
public TestHierarchyNodeModel[] ChildNodes { get; set; }
[XmlAttribute("this")]
public string GUID { get; set; }
}
public class ComponentModel {
[XmlAttribute("this")]
public string GUID { get; set; }
[XmlAttribute("id")]
public string Id { get; set; }
}
With using the above, the LayoutModel deciphers fine, and I get the Hierarchy -> Root connection, but "ChildNodes" in the Root is null, so nothing beneath it is deserialized. Likewise, the "Components" array is empty, at size 0.
Simple example XML structure for this problem at hand:
<?xml version="1.0"?>
<layout
version="137"
comment=""
precache_condition="">
<hierarchy>
<root this="2A19D461-6F9E-45F7-977F41D42D07FDB0">
<template_row_header this="F3416CFD-8BC7-4276-86996FD67D7F6A75">
<dy_title this="77E6B934-1E3B-40E5-BC14C7F643672167"/>
</template_row_header>
</root>
</hierarchy>
<components>
<root
this="2A19D461-6F9E-45F7-977F41D42D07FDB0"
id="root">
</root>
<template_row_header
this="F3416CFD-8BC7-4276-86996FD67D7F6A75"
id="template_row_header"
offset="0.00,4.00">
</template_row_header>
<dy_title
this="77E6B934-1E3B-40E5-BC14C7F643672167"
id="dy_title"
offset="0.00,0.00">
</dy_title>
</components>
</layout>

<hierarchy>have the same schema when they appear under<components>? E.g. is<template_row_header>appears under both but has more attributes under<components>. Are those attributes optional? Could a<template_row_header>element have those same attributes no matter where it appears?