使用 C# 进行 XML 验证
Posted
技术标签:
【中文标题】使用 C# 进行 XML 验证【英文标题】:XML validation with C# 【发布时间】:2021-08-01 12:07:04 【问题描述】:大家好! 我在尝试根据其架构验证 XML 文件时遇到一些问题。 我拥有的 XML 文件如下所示:
<?xml version="1.0" encoding="utf-8"?>
<game:gameXML xmlns:game="national:game" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<From description="Gamer">Gamer</From>
<To description="Player">Player</To>
<MessageId>1620711716</MessageId>
<MessageDate>2021-05-11T15:41:53</MessageDate>
<TransactionGroup>Ball</TransactionGroup>
<Priority>Medium</Priority>
<SecurityContext>CONTACT_PERSON_GOES_HERE</SecurityContext>
<Market>Japan</Market>
</Header>
<Transactions>
<Transaction transaction="1620711716">
<ReportRequest>
<ReportParameters xsi:type="game:reportParameters">
<ReportName>All</ReportName>
<FromDate>2005-01-01</FromDate>
<ToDate>2021-05-11</ToDate>
</ReportParameters>
</ReportRequest>
</Transaction>
</Transactions>
</game:gameXML>
我使用 VS 2019 生成了相应的架构,这给了我这个:
xmlFile.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:game="national:game" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="national:game" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="xmlContent.xsd" />
<xs:element name="gameXML">
<xs:complexType>
<xs:sequence>
<xs:element ref="Header" />
<xs:element ref="Transactions" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
和
xmlContent.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Header">
<xs:complexType>
<xs:sequence>
<xs:element name="From">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="description" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="To">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="description" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="MessageId" type="xs:unsignedInt" />
<xs:element name="MessageDate" type="xs:dateTime" />
<xs:element name="TransactionGroup" type="xs:string" />
<xs:element name="Priority" type="xs:string" />
<xs:element name="SecurityContext" type="xs:string" />
<xs:element name="Market" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Transactions">
<xs:complexType>
<xs:sequence>
<xs:element name="Transaction">
<xs:complexType>
<xs:sequence>
<xs:element name="ReportRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="ReportParameters">
<xs:complexType>
<xs:sequence>
<xs:element name="ReportName" type="xs:string" />
<xs:element name="FromDate" type="xs:date" />
<xs:element name="ToDate" type="xs:date" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="transaction" type="xs:unsignedInt" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
我用来加载这些的代码是:
XmlReaderSettings settings = new XmlReaderSettings DtdProcessing = DtdProcessing.Parse ;
XmlSchemaSet xs = new XmlSchemaSet();
xs.Add("national:game", "xmlFile.xsd");
xs.Add("national:game", "xmlContent.xsd");
xs.Compile();
我一运行它就会报错:
System.Exception: This is an invalid xsi:type 'national:game:reportParameters'.
显然它将命名空间注入xmlContent.xsd
文件,我不知道需要设置什么来防止这种情况。事实上,这个 .xsd 文件应该有它自己的命名空间(参见实际 .xml 文件中的<ReportParameters xsi:type="game:reportParameters">
)。
任何线索、指示或帮助将不胜感激。 谢谢。
【问题讨论】:
我得到一个完全不同的错误 -System.Xml.Schema.XmlSchemaException: 'The 'Header' element is not declared.'
- 这是我第一次尝试运行你的代码的机会。我已经准确地复制了每个代码示例。此外,您提到的作为问题的类型注释在实例文档中,并且您没有提到任何针对已编译的 XmlSchemaSet 进行验证的代码,因此使用给定的信息无法重现这一点。我可以看到 ref="Header"
声明没有被识别,我很感激你提供让你通过的代码。
【参考方案1】:
没有任何类型被命名,因此看起来除了架构内置类型之外,xsi:type
没有有效值,因为所有 complexTypes 都是匿名的。
这是 xsd.exe(用于生成架构的工具)受到限制的一个方面,因为根据定义,如果存在 xsi:type 属性,它必须引用架构声明的某些类型,但生成的架构声明没有命名类型。然而,它的目的是解决歧义,因此同样的工具引入歧义是不合逻辑的。
要解决此问题,请重组 xmlContent.xsd
以全局声明 reportParameters
类型并引用它,即
<xs:element name="ReportParameters" type="game:reportParameters"/>
<xs:complexType name="reportParameters">
...
【讨论】:
谢谢@Tom。但不起作用:System.Xml.Schema.XmlSchemaException:无法从位置“xmlContent.xsd”加载架构-“type”属性的值无效-“game:reportParameters”是“type”的无效值' 属性。此外,“xs:complexType”中不允许使用“name”属性 关于第二个错误,我不知道该告诉你什么,因为我已经使用过很多次了,所以可以 100% 确定它是正确的。也许检查XML Schema spec 是否正确声明了所有元素。我会坚持我的回答原则,即 xsi:type 需要一个命名类型,而模式生成器不够复杂,无法处理这个问题。 第二个错误我不太确定,但看起来这是第一个错误的结果;如果它要引用的 complexType 在某些方面是错误的,那么它不会引用一个有效的名称。以上是关于使用 C# 进行 XML 验证的主要内容,如果未能解决你的问题,请参考以下文章