Reputation: 7693
I'm trying to write a generic method that can be used to deserialize xml to an array of objects.
Given XML that looks like so:
<people>
<person>
<someElement>content</someElement>
</person>
<person>
<someElement>more content</someElement>
</person>
</people>
Shown in the below code as xmlDoc
. And a person
class as T
XmlNodeReader reader = new XmlNodeReader(xmlDoc.DocumentElement);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T[]), new XmlRootAttribute(xmlDoc.DocumentElement.Name));
results = xmlSerializer.Deserialize(reader) as T[];
This works as expected, and returns person[]
with 2 entries.
However, in the API I am working with, if there is only 1 result returned, it just returns:
<person>
<someElement>content</someElement>
</person>
And my deserialization breaks down. person[]
remains empty.
Any thoughts on the best way to implement this?
I'm contemplating running an XSLT in between, and passing the name of T
in, if it matches the root node, then add a wrapping node?
Upvotes: 2
Views: 1121
Reputation: 7693
I ended up using XSLT to ensure the node(s) I was after weren't the root.
Basically I've a XSLT file containing:
<xsl:template match="/">
<rootNode>
<xsl:apply-templates select="node()|@*"/>
</rootNode>
</xsl:template>
(Not sure if this XSLT is ideal, would love some comments).
This wraps a around my inbound XML from the api. My previously mentioned Person
class has a [XmlType("person")]
attribute applied to it, armed with that I can do:
//using reflection to look what the XmlType has been declared on this type
var typeAttributes = Attribute.GetCustomAttribute(typeof(T), typeof(XmlTypeAttribute));
//determine an xpath query to find this type of elements parent
string xPathtoTypeName = string.Format("//{0}/parent::node()", ((XmlTypeAttribute)typeAttributes).TypeName);
//use the above xpath query to find the parent node.
var parentNode = transformedDocument.SelectSingleNode(xPathtoTypeName);
//deserialize as before
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T[]), new XmlRootAttribute(parentNode.Name));
XmlNodeReader nodeReader = new XmlNodeReader(parentNode);
results = xmlSerializer.Deserialize(nodeReader) as T[];
Upvotes: 1
Reputation: 28345
Check Name of the Root element, and if it is not people
, add it to xml, and everything will go fine.
Update:
Check deep of the xml document, and if its == 2, create root element.
Another way - use of LINQ-TO-XML
XElement.Descandants("person")
- array of person
-elements
Upvotes: 0