创建 C# 模型以反序列化 XML 提要

Posted

技术标签:

【中文标题】创建 C# 模型以反序列化 XML 提要【英文标题】:Creating C# models to deserialize XML feeds 【发布时间】:2021-12-22 06:35:18 【问题描述】:

我正在构建一个 .net5 应用程序来抓取 RSS 提要,并且我想避免自定义字符串解析逻辑。相反,我想直接序列化 c# 对象中的 XML。我以前做过一次,我使用 xsd.exe 生成架构文件,然后从中生成 .cs 文件。但是,这一次不起作用。这是我要抓取的内容

<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        <item>
            <title>Fire kills four newborn babies at children's hospital in India</title>
            <link>http://news.sky.com/story/india-fire-kills-four-newborn-babies-at-childrens-hospital-in-madhya-pradesh-12464344</link>
            <description>Four newborn babies have died after a fire broke out at a children's hospital in India, officials said.</description>
            <pubDate>Tue, 09 Nov 2021 07:51:00 +0000</pubDate>
            <guid>http://news.sky.com/story/india-fire-kills-four-newborn-babies-at-childrens-hospital-in-madhya-pradesh-12464344</guid>
            <enclosure url="https://e3.365dm.com/21/11/70x70/skynews-india-fire-childrens-hospital_5577072.jpg?20211109081515" length="0" type="image/jpeg" />
            <media:description type="html">A man carries a child out from the Kamla Nehru Children’s Hospital after a fire in the newborn care unit of the hospital killed four infants, in Bhopal, India, Monday, Nov. 8, 2021. There were 40 children in total in the unit, out of which 36 have been rescued, said Medical Education Minister Vishwas Sarang. (AP Photo) </media:description>
            <media:thumbnail url="https://e3.365dm.com/21/11/70x70/skynews-india-fire-childrens-hospital_5577072.jpg?20211109081515"   />
            <media:content type="image/jpeg" url="https://e3.365dm.com/21/11/70x70/skynews-india-fire-childrens-hospital_5577072.jpg?20211109081515" />
            ...
        </item>
    </channel>
</rss>

到目前为止,我已经尝试过使用 xsd.exe 和这个在线工具:https://xmltocsharp.azurewebsites.net/。两者都遇到了&lt;description&gt;&lt;media:description&gt; 标签的问题——它试图在item 内创建第二个“描述”元素,但失败了:

    xsd.exe 执行失败并且不生成类,除非我删除其中一个。 在线工具生成类,但当我尝试使用它们实例化 XmlSerializer 时,这些类会失败

我可以看到有两个 description 标签,但其中一个是在媒体命名空间中定义的。就 xsd 和 .net 而言,这些标签应该映射到相同的属性,这显然是一个问题。这是一个无效的 XML,还是这些工具中存在某种限制,阻止了成功的映射。除了字符串解析还有其他解决方法吗?

【问题讨论】:

【参考方案1】:

问题是您必须向 xsd.exe 提供“媒体”架构定义。 Media RSS Specification 是“媒体”命名空间的完整描述。不幸的是,我找不到任何 XSD 文件,但可以从您提供的 XML 生成一个。我为此使用 Visual Studio,可能还有其他工具可以做到这一点(在 Visual Studio 中打开文件,从菜单“XML”-“创建模式”中选择)。如规范中所述,Visual Studio 可能不会生成完整的架构,而只会生成它可以在 XML 中检测到的内容。获得 XSD 文件后,您必须创建“媒体”模式文件。这是我从您的示例中生成的内容:

文件rss.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:import namespace="http://search.yahoo.com/mrss/" schemaLocation="media.xsd" />
    <xs:element name="rss">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="channel">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="item">
                                <xs:complexType mixed="true">
                                    <xs:sequence>
                                        <xs:element name="title" type="xs:string" />
                                        <xs:element name="link" type="xs:string" />
                                        <xs:element name="description" type="xs:string" />
                                        <xs:element name="pubDate" type="xs:string" />
                                        <xs:element name="guid" type="xs:string" />
                                        <xs:element name="enclosure">
                                            <xs:complexType>
                                                <xs:attribute name="url" type="xs:string" use="required" />
                                                <xs:attribute name="length" type="xs:unsignedByte" use="required" />
                                                <xs:attribute name="type" type="xs:string" use="required" />
                                            </xs:complexType>
                                        </xs:element>
                                        <xs:element ref="media:description" />
                                        <xs:element ref="media:thumbnail" />
                                        <xs:element ref="media:content" />
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="version" type="xs:decimal" use="required" />
        </xs:complexType>
    </xs:element>
</xs:schema>

文件media.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://search.yahoo.com/mrss/"> 
    <xs:element name="description">
        <xs:complexType>
            <xs:simpleContent>
                <xs:extension base="xs:string">
                    <xs:attribute name="type" type="xs:string" use="required" />
                </xs:extension>
            </xs:simpleContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="thumbnail">
        <xs:complexType>
            <xs:attribute name="url" type="xs:string" use="required" />
            <xs:attribute name="width" type="xs:unsignedByte" use="required" />
            <xs:attribute name="height" type="xs:unsignedByte" use="required" />
        </xs:complexType>
    </xs:element>
    <xs:element name="content">
        <xs:complexType>
            <xs:attribute name="type" type="xs:string" use="required" />
            <xs:attribute name="url" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
</xs:schema>

如果需要,您可以扩展 XSD 文件 - 完整规范在上面的链接中。现在调用 xsd.exe

c:\temp>xsd.exe media.xsd rss.xsd /c

将生成 c# 类。

【讨论】:

那行得通。我正在做同样的事情,使用 xsd.exe 而不是 VS。它创建了额外的模式,我在制作类时引用了所有模式。但是,它显然无法处理重复的“描述”节点。谢谢。 但是我可能最终不会使用这个,因为我需要模型的序列化输出与原始输入相同。目前输出有所不同,这可能是后续服务的问题。

以上是关于创建 C# 模型以反序列化 XML 提要的主要内容,如果未能解决你的问题,请参考以下文章

无法反序列化 xml 数组以列出 web api 模型 c#

有没有办法让 Spring Boot 反序列化以反序列化测试中的对象?

C# 将 XML 反序列化为模型类错误 - <xmlns=""> 不是预期的

拆分 JSON 字符串的一部分以反序列化

C# 使用多个可能的命名空间反序列化 xml

如何将 XML 反序列化为 C# 中的对象? [复制]