将 XML 反序列化为对象数组或单个对象

发布于 2024-09-06 02:15:08 字数 1014 浏览 4 评论 0原文

我正在尝试编写一个通用方法,可用于将 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 的名称,如果它与根节点匹配,然后添加一个包装节点?

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?

Edit

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

筱果果 2024-09-13 02:15:08

我最终使用 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[];

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[];
七颜 2024-09-13 02:15:08

检查 Root 元素的 Name,如果不是 people,则将其添加到 xml 中,一切都会正常。


更新:
检查 xml 文档的深度,如果其 == 2,则创建根元素。
另一种方法 - 使用 LINQ-TO-XML
XElement.Descandants("person") - person 元素数组

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文