2016-06-07 64 views
0

我試圖生成一個XSD來驗證具有未知深度的XML。這是通過來自XML的XSLT完成的。 XML有點類似於類的描述,每個節點都包含有關屬性和子節點的信息。 XSD必須檢查另一個包含實例的XML。因此,XSD必須檢查一個實例是否具有來自其類的所有屬性,並且它是祖先。XSD多個級別的擴展問題

這就是爲什麼我試圖解決我的問題與類型相互擴展。

XML測試文件:

<!-- language:xml --> 
<?xml version="1.0" encoding="UTF-8"?> 
<CAEXFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      FileName="Visu_Ruehrreaktor.aml" 
      SchemaVersion="2.15" 
      xsi:noNamespaceSchemaLocation="Validation.xsd"> 
    <HMI> 
     <HMIGraphic Name="Visu_Ruehrreaktor" 
        RefBaseSystemUnitPath="HMISUCLib/Graphic" 
        ID="dce863ca-795b-4d54-9a4c-789b0204f243"> 
     <h>1080</h> 
     <w>1920</w> 
     <HMIVisuObjectTextBoxTermination Name="Text01" 
              RefBaseSystemUnitPath="HMISUCLib/VisuObject/TextBox/Termination" 
              ID="c0215848-b8b6-4f76-aa2c-3996a053f3fc"> 
      <text/> 
      <tagname>Text01</tagname> 
      <x>178</x> 
      <y>152</y> 
      <h>37</h> 
      <w>139</w> 
      <role/> 
      <type>0001</type> 
      <rotation>01</rotation> 
      <com_id/> 
     </HMIVisuObjectTextBoxTermination> 
     </HMIGraphic> 
    </HMI> 
</CAEXFile> 

XSD:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
    <xs:complexType name="HMI_type"> 
     <xs:choice maxOccurs="unbounded"> 
     <xs:element name="HMIGraphic" type="HMIGraphic_type" minOccurs="0"/> 
     </xs:choice> 
    </xs:complexType> 

    <xs:complexType name="HMIVisuObject_type"> 
     <xs:choice maxOccurs="unbounded"> 
     <xs:element name="tagname" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="x" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="y" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="h" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="w" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="role" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="type" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="rotation" minOccurs="1" maxOccurs="1"/> 
     </xs:choice> 
     <xs:attribute name="Name" type="xs:string" use="required"/> 
     <xs:attribute name="RefBaseSystemUnitPath" type="xs:string" use="required"/> 
     <xs:attribute name="ID" type="xs:string" use="required"/> 
    </xs:complexType> 

    <xs:complexType name="HMIVisuObjectTextBox_type"> 
     <xs:complexContent> 
     <xs:extension base="HMIVisuObject_type"> 
      <xs:choice maxOccurs="unbounded"> 
       <xs:element name="text" minOccurs="1" maxOccurs="1"/> 
      </xs:choice> 
     </xs:extension> 
     </xs:complexContent> 
    </xs:complexType> 
    <xs:complexType name="HMIVisuObjectTextBoxTermination_type"> 
     <xs:complexContent> 
     <xs:extension base="HMIVisuObjectTextBox_type"> 
      <xs:choice maxOccurs="unbounded"> 
      </xs:choice> 
     </xs:extension> 
     </xs:complexContent> 
    </xs:complexType> 
    <xs:complexType name="HMIGraphic_type"> 
     <xs:choice maxOccurs="unbounded"> 
     <xs:element name="HMIVisuObject" type="HMIVisuObject_type" minOccurs="0"/> 
     <xs:element name="HMIVisuObjectTextBox" 
        type="HMIVisuObjectTextBox_type" 
        minOccurs="0"/> 
     <xs:element name="HMIVisuObjectTextBoxTermination" 
        type="HMIVisuObjectTextBoxTermination_type" 
        minOccurs="0"/> 
     <xs:element name="h" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="w" minOccurs="1" maxOccurs="1"/> 
     </xs:choice> 
     <xs:attribute name="Name" type="xs:string" use="required"/> 
     <xs:attribute name="RefBaseSystemUnitPath" type="xs:string" use="required"/> 
     <xs:attribute name="ID" type="xs:string" use="required"/> 
    </xs:complexType> 

    <xs:element name="CAEXFile"> 
     <xs:complexType> 
     <xs:all> 
      <xs:element name="HMI" type="HMI_type" minOccurs="0"/> 
     </xs:all> 
     <xs:anyAttribute processContents="skip"/> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

的問題是,當過我運行驗證,找到類型的元素HMIVisuObjectTextBoxTermination_type我得到一個錯誤,說文本不允許作爲元素。

輸出/ To_Check.aml:15:元素文本:模式有效性錯誤:元素'文本':該元素不是期望的。預期是(標記名,x,y,h,w,角色,類型,旋轉)之一。

所以基本上只有這個類型鏈的根元素的元素。我做錯了什麼,我怎麼能解決這個問題。

由於提前

+0

添加了這兩個文件。我希望它有幫助。 – Tyreal

回答

0

你的複雜類型HMIVisuObjectTextBoxTermination_type可能有一個有效的內容模型這是不是你期待什麼。在XSD 1.0中,複雜類型的擴展會創建一個序列,首先包含基本類型的內容模型,然後是擴展添加的材料。 (有些人認爲這很有幫助,認爲這與在結構的末尾添加新字段類似,用於擴展OO語言中的基類。)由於您有擴展名的擴展名,因此您的效果:

<xs:sequence> 
    <!--* complex type HMIVisuObjectTextBox_type *--> 
    <xs:sequence> 
    <!--* complex type HMIVisuObject_type *--> 
    <xs:choice maxOccurs="unbounded"> 
     <xs:element name="tagname" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="x" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="y" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="h" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="w" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="role" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="type" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="rotation" minOccurs="1" maxOccurs="1"/> 
    </xs:choice> 
    <xs:choice maxOccurs="unbounded"> 
     <xs:element name="text" minOccurs="1" maxOccurs="1"/> 
    </xs:choice> 
    </xs:sequence> 
    <xs:choice maxOccurs="unbounded"> 
    </xs:choice> 
</xs:sequence> 

有效實例必須包含其是三個子序列的串聯元件的序列,其匹配:

  • 第一一個或多個標記名,X,Y的,H,W,角色,類型或旋轉,後跟
  • 一個或多個文字,後跟
  • 一個或多個空集。

您在這裏有兩個問題:首先,你的XML來看,你預計text被添加到該組可能孩子在重複的選擇,而不是被要求來所有的人後。其次,當下一個輸入項與其子項中的某一個相匹配時,內容模型中的選擇得以滿足;一個空的選擇沒有孩子,所以沒有任何東西可以匹配任何一個。如果選擇是必需的,作爲該序列的第三選擇,則選擇是不可滿足的。這意味着它的包含序列是不可滿足的,這意味着它的包含序列是不可滿足的,這意味着類型HMIVisuObjectTextBoxTermination_type沒有有效的實例。給出選擇minOccurs="0"將允許該類型具有有效的實例,但它們不會被允許具有第一個text元素。

[附錄] OP問:「那麼,有沒有一種方式,而不是試圖讓我的XSLT遞歸中,我複製了父母的所有屬性的方式,並創建一個新的類型...?我基本上要do實際上是將文本添加到選項列表中,因爲它們都需要以xml存在,但它們可以以任何順序存在。「

幾種可能的方法提供自己:

  • 指定爲孩子們一個固定的順序。如果孩子的順序是固定的,那麼類型推導問題就變得微不足道了。

    所以我會非常仔細地研究兒童的秩序必須不受限制的前提;這比聲稱要多得多。如果兒童的序列攜帶信息(如通常在自然語言文件中所做的那樣),這是真的;懷疑序列是否不包含信息。

  • 爲HMIVisuObject_type,HMIVisuObjectTextBox_type等中的選項定義命名的模型組。在相應的命名模型組中定義各種類型的問題。

    <xs:group name="A"> 
        <xs:element ref="tagname"/> 
        <xs:element ref="x"/> 
        <xs:element ref="y"/> 
        ... 
    </ 
    <xs:group name="B"> 
        <xs:element ref="text"/> 
        ... 
    </ 
    <xs:group name="C"> 
        ... 
    </ 
    
    <xs:complexType name="HMIVisuObject_type"> 
        <xs:choice minOccurs="0" maxOccurs="unbounded" ref="A"/> 
        ... 
    </ 
    <xs:complexType name="HMIVisuObjectTextBox_type"> 
        <xs:choice minOccurs="0" maxOccurs="unbounded"> 
        <xs:choice ref="A"/> 
        <xs:choice ref="B"/> 
        </ 
        ... 
    </ 
    <xs:complexType name="HMIVisuObjectTextBoxTermination_type"> 
        <xs:choice minOccurs="0" maxOccurs="unbounded"> 
        <xs:choice ref="A"/> 
        <xs:choice ref="B"/> 
        <xs:choice ref="C"/> 
        </ 
        ... 
    </ 
    

    這顯示出三種類型之間的關係清楚地給讀者,並避免了同一事物的多個規格。它沒有通過類型之間的基類型/派生類型關係來展示關係,並且在某些環境中,它會減少幫助。 (但是如果你依賴於一個面向OO類系統的映射,你將不會首先使用可重複的選擇,所以對你來說可能並不重要,儘管這對某些用戶很重要。)

  • 反轉類型層次結構:將最包含的類型定義爲類型,將其他類型定義爲它的限制。

    這展示了使用基本/派生鏈接的類型之間的關係,但是定向鏈接可能不是您想要的方向。

  • 如果您使用的是XSD 1.1,請將這些類型的選項替換爲所有組;在XSD 1.1中,由所有組擴展的所有組的基本類型會生成較大的所有組。

+0

這聽起來不太好,但迄今爲止感謝! 好的空集可以在我的XSLT中修復。但是這並不能解決我的問題。 那麼有沒有另一種方法比嘗試使我的XSLT遞歸方式,我複製所有的父母屬性和創建一個新的類型,忘記解決方案? 我基本上想要做的事實上是將文本添加到選項列表中,因爲它們都需要以xml存在,但它們可以以任何順序存在。 – Tyreal