2013-05-26 72 views
5

作为一名具有大量XML消费和生产经验的开发人员,我从未真正与模式进行过交互。这是我第一次实际发生。使用XSD正确验证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); 
     }); 
    } 

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

+0

Xsd验证通常仅在找不到所需架构时才会生成警告。你很可能只会检查错误。 –

+1

这不是这种情况,请参阅:http://msdn.microsoft.com/en-us/library/bb354954(v=vs.90).aspx XDocument.Validate的详细信息。验证的这个特定的重载将会捕获错误和警告。 –

回答

3

您的XML中没有可以通过架构进行验证的节点(名称空间不同)。因此它不报告任何错误。据我所知,与任何模式不匹配的节点的行为都是允许的。

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

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

退房XmlSchemaSet.AddHOW TO: Validate an XML Document by Using Multiple Schemas如果你希望从多个命名空间节点出现在XML。

+0

在这种情况下,真正的问题是在XmlSchemaSet模式中不存在与文档根中指定的名称空间的模式匹配的模式吗?不应该强制执行吗? –

+0

@DanielGreen它是,但我不记得如何...我已添加链接到报告警告,所以它应该让你知道没有模式的元素。 –

+0

这一切都很好,但目前的设计需要一个XDocument,我宁愿不改变它,但加载流两次似乎也是错误的,特别是因为在这种情况下,它不清楚要加载什么。 –