正确验证XSD的XML文档

Dan*_*een 5 .net c# xml schema

作为一名拥有大量XML消费和生产经验的开发人员,我以前从未真正与模式交互过.这是第一次真正发生在我身上.

我遇到了一个"功能",我认为它更像是一个记录良好的错误.

使用XDocument.Validate()时,似乎有些情况下,如果文档与指定的模式不匹配,则文档将有效.我觉得这很可能是我理解XSD,XML命名空间和预期验证过程之间关系的一个缺陷.

因此,我向您提交了我的XML示例,我的XSD示例和我的验证代码.

XML - 这本质上是错误的文档.

<?xml version="1.0" encoding="utf-8" ?>
<SuppliesDefinitions 
  xmlns="http://lavendersoftware.org/schemas/SteamGame/Data/Xml/Supplies.xsd">
  <Supply type="Common">
    <Information/>
    <Ritual/>
    <Weapon/>
    <Tool count="1"/>
    <Tool count="2"/>
    <Tool count="3"/>
  </Supply>
  <Supply type="Uncommon">
    <Information/>
    <Weapon/>
    <Tool count="1"/>
    <Tool count="2"/>
    <Tool count="3"/>
    <Tool count="4"/>
  </Supply>
  <Supply type="Rare">
    <Information/>
    <Rune/>
    <Weapon/>
    <Tool count="2"/>
    <Tool count="3"/>
    <Tool count="4"/>
  </Supply>
</SuppliesDefinitions>
Run Code Online (Sandbox Code Playgroud)

XSD用于验证它.(同样,这是上述XML的WRONG文档)

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Encounters"
    targetNamespace="http://lavendersoftware.org/schemas/SteamGame/Data/Xml/Encounters.xsd"
    elementFormDefault="qualified"
    xmlns="http://lavendersoftware.org/schemas/SteamGame/Data/Xml/Encounters.xsd"
    xmlns:mstns="http://lavendersoftware.org/schemas/SteamGame/Data/Xml/Encounters.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:complexType name="ToolType">
    <xs:attribute name="count" use="required" type="xs:int"/>
  </xs:complexType>

  <xs:complexType name="TaskType">
    <xs:choice maxOccurs="unbounded" minOccurs="1">
      <xs:element name="Weapon"/>
      <xs:element name="Information"/>
      <xs:element name="Tool" type="ToolType"/>
      <xs:element name="Ritual"/>
    </xs:choice>
  </xs:complexType>


  <xs:complexType name="EncounterType">
    <xs:sequence maxOccurs="unbounded" minOccurs="1">
      <xs:element name="Task" type="TaskType"/>
    </xs:sequence>
    <xs:attribute name="name" use="required" type="xs:string"/>
  </xs:complexType>

  <xs:element name="EncounterDefinitions">
    <xs:complexType>
      <xs:sequence maxOccurs="unbounded" minOccurs="1">
        <xs:element name="Encounter" type="EncounterType"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

最后是验证码.

    private static void ValidateDocument(XDocument doc)
    {
        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add(null, XmlReader.Create(new StreamReader(XmlSchemaProvider.GetSchemaStream("Encounters.xsd"))));

        doc.Validate(schemas, (o, e) =>
        {
            //This is never hit!
            Console.WriteLine("{0}", e.Message);
            Assert.False(e.Severity == XmlSeverityType.Error);
        });
    }
Run Code Online (Sandbox Code Playgroud)

我想知道是否有人可以解释我做错了什么.我觉得我对这个应该采用的方式做了一些不正确的假设.在我看来,对一个完全不相关的XML文档使用一个xsd将是无效的.

Ale*_*kov 4

XML 中没有可以由架构验证的节点(命名空间不同)。结果它不会报告任何错误。据我所知,与任何模式不匹配的节点的行为是允许任何行为的。

您还可以在 XmlReaderSettings 中设置验证选项以允许警告:

ReportValidationWarnings - 指示如果发生验证警告则应报告事件。当没有 DTD 或 XML 模式来验证特定元素或属性时,通常会发出警告。ValidationEventHandler 用于通知。

如果您希望 XML 中出现来自多个命名空间的节点,请查看XmlSchemaSet.Add如何:使用多个架构验证 XML 文档