【问题标题】:Validating XML documents with XSD correctly使用 XSD 正确验证 XML 文档
【发布时间】:2013-05-21 05:46:44
【问题描述】:

作为一名拥有大量 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>

用于验证它的 XSD。 (同样,这是故意为上述 XML 错误的文档)

<?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>

最后是验证码。

    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);
        });
    }

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

【问题讨论】:

  • Xsd 验证通常仅在找不到所需架构时生成警告。您可能只是在检查错误。
  • 这里不是这种情况,有关 XDocument.Validate 的详细信息,请参阅:msdn.microsoft.com/en-us/library/bb354954(v=vs.90).aspx。这种特殊的 validate 重载将捕获错误和警告。

标签: c# .net xml schema


【解决方案1】:

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

您也可以设置validation options in XmlReaderSettings 以允许警告:

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

如果您希望 XML 中出现来自多个命名空间的节点,请查看 XmlSchemaSet.AddHOW TO: Validate an XML Document by Using Multiple Schemas

【讨论】:

  • 在这种情况下,真正的问题是 XmlSchemaSet 架构中不存在与文档根目录中指定的命名空间的架构匹配的架构,不是吗?这不应该是可执行的吗?
  • @DanielGreen 是,但我不记得如何...我添加了报告警告的链接,因此它应该让您知道没有架构的元素。
  • 这一切都很好,但是当前的设计采用 XDocument,我宁愿不改变它,但是两次加载流似乎也是错误的,特别是因为在这种情况下不清楚什么加载。
  • 有同样的问题。 .NET 的这一部分在“最小化原则”上确实失败了。
  • 另外,请注意,这实际上根本没有帮助 - .net 验证器也不认为这是一个警告。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 2014-01-22
  • 2019-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多