我正在尝试编写一个可用于将xml反序列化为对象数组的泛型方法。
鉴于XML看起来如此:
<people>
<person>
<someElement>content</someElement>
</person>
<person>
<someElement>more content</someElement>
</person>
</people>
以下代码显示为xmlDoc
。 person
等级为T
XmlNodeReader reader = new XmlNodeReader(xmlDoc.DocumentElement);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T[]), new XmlRootAttribute(xmlDoc.DocumentElement.Name));
results = xmlSerializer.Deserialize(reader) as T[];
这可以按预期工作,并返回带有2个条目的person[]
。
但是,在我正在使用的API中,如果只返回1个结果,则只返回:
<person>
<someElement>content</someElement>
</person>
我的反序列化打破了。 person[]
仍为空。
有关实施此方法的最佳方式的任何想法?
我正在考虑在其间运行XSLT,并传入T
的名称,如果它与根节点匹配,那么添加一个包装节点?
答案 0 :(得分:1)
我最终使用XSLT来确保我所关注的节点不是根。
基本上我有一个包含以下内容的XSLT文件:
<xsl:template match="/">
<rootNode>
<xsl:apply-templates select="node()|@*"/>
</rootNode>
</xsl:template>
(不确定这个XSLT是否理想,会喜欢一些评论)。
这包含了来自api的入站XML。我之前提到的Person
类已应用[XmlType("person")]
属性,我可以这样做:
//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[];
答案 1 :(得分:0)
检查Root元素的名称,如果它不是people
,则将其添加到xml中,一切都会正常。
更新:
检查xml文档的深层,如果它的== 2,则创建根元素。
另一种方式 - 使用LINQ-TO-XML
XElement.Descandants("person")
- person
- 数组