2013-05-26 115 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,我寧願不改變它,但加載流兩次似乎也是錯誤的,特別是因爲在這種情況下,它不清楚要加載什麼。 –