2013-02-27 57 views
0

我們正在嘗試爲我們的XSD提供一個好的模型。這是問題:多級XSD​​約束

List 
I-> Item1 
     I->Element1 
     I->Element2 
     I->Element3  
I-> Item2 
     I->Element1 
     I->Element2 
     I->Element3 
I-> Item3 
     I->Element1 
     I->Element2 
     I->Element3 

ReferenceToElement 
I-> Item1/Element1 

我們得到了一個模型,我們需要兩個嵌套列表。所以有一個帶有「項目」的列表,每個項目都有一個包含元素的列表。所以我們想引用這些元素。

第一種方法

每個項目/元素確實有一些屬性。數字屬性在所有項目中都是唯一的。此外,數字屬性在所有元素中都是唯一的,因爲父項的編號以其編號進行編碼。例如,對於item.no = 2,所有元素將看起來像這個2xx,所以201,202等。這當然會將元素限制爲100,這對我們來說很好。

爲了保持所引用元素的存在性,我們創建了一個約束條件,使所有條目都是唯一的以及所有條目中的所有元素。所以我們參考一個元素看起來就像這樣

Reference 
    - ItemNo 
    - ElementNo 

這樣我們確保項目以及元素存在。我知道這兩個戰隊之間存在一個問題,因爲引用的項目不一定在elementno中隱含地陳述。例如ItemNo = 1,但ElementNo = 202。這種方式驗證會告訴我們至少這些元素是否存在。主要的缺點是我們需要關注所有殺死我們的元素中數字的正確分配。

第二條本辦法

我們不會使用該約束的elementNo,但留在貨號。這樣我們就可以在所有元素上使用簡單的數字,但是在模式驗證期間,我們會放棄elementNo上的參考迭代。這對我們來說似乎是最好的方式。

問:

有沒有一種方法來模擬兩上演着XSD能力的參考?我讀了一些關於斷言的內容,但在這種情況下它似乎沒有幫助我們。

回答

0

[請注意,如果您實際顯示了一些XML,那麼理解您的問題會更容易一些。事實上,任何答案都必須部分基於對你的散文描述打算描述的XML構造的猜測;然後,帶上一粒鹽。]

如果我理解你,你想要施加一些限制(此編號以供參考):

  1. 每個<element>元素顯示爲<item>元素的子元素。

  2. 每個<element><item>元素具有number屬性,其值是一個標識號;每個number屬性的值是一個十進制數字的有限序列。

  3. 每個<item>元素的識別號在整個<item>元素中是唯一的,這些元素在一些識別的容器元素中是唯一的。文檔元素)。

  4. 每個<element>元素的標識號在同一容器元素中的所有<element>元素中都是唯一的。 (也許你的意思,它是跨包含項中的所有元素<element>獨特?我無法從你的描述出來。)

  5. 每個<element>元素的識別號將有父<item>元素的標識號作爲前綴。

  6. 每個<element>元素的標識號碼將比父<item>元素的標識號碼精確地長兩位數。

以下架構強加這些約束。既然你提到了斷言,我認爲你能夠使用XSD 1.1。 (如果你沒有做1.1,你沒有斷言。)

<xs:schema 
    targetNamespace="http://example.com/elements-and-items" 
    xmlns:tns="http://example.com/elements-and-items" 
    elementFormDefault="qualified" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

    <xs:element name="test" type="tns:test"> 
    <xs:unique name="item-unique"> 
     <xs:annotation> 
     <xs:documentation> 
      Ensure that the number attribute on each 
      item is unique within the 'test' element. 
      (Enforces constraint 3.) 
     </xs:documentation> 
     </xs:annotation> 
     <xs:selector xpath=".//tns:item"/> 
     <xs:field xpath="@number"/> 
    </xs:unique> 
    <xs:unique name="element-unique"> 
     <xs:annotation> 
     <xs:documentation> 
      Ensure that the number attribute on each 
      item is unique within the 'test' element. 
      (Enforces constraint 4. If 'element' elements 
      are only supposed to be unique within 'item' 
      elements, then move this to the declaration of 
      the 'item' element, and forget constraint 
      5.)      
     </xs:documentation> 
     </xs:annotation> 
     <xs:selector xpath=".//tns:item/tns:element"/> 
     <xs:field xpath="@number"/> 
    </xs:unique> 

    </xs:element> 

    <xs:element name="item" type="tns:item"/> 

    <xs:element name="element" type="tns:element"/> 

    <xs:complexType name="test"> 
    <xs:annotation> 
     <xs:documentation> 
     Each 'test' element contains a sequence of 
     'item' elements. 
     (Helps enforce constraint 1.) 
     </xs:documentation> 
    </xs:annotation> 
    <xs:sequence> 
     <xs:element ref="tns:item" maxOccurs="unbounded"/> 
    </xs:sequence>   
    </xs:complexType> 

    <xs:complexType name="item"> 
    <xs:annotation> 
     <xs:documentation> 
     Each 'item' element contains a sequence of 
     'element' elements. 
     (Helps enforce constraint 1.) 
     Each 'item' element has a 'number' attribute, 
     of type 'tns:number'. 
     (Enforces constraint 2 for 'item' elements.) 
     </xs:documentation> 
    </xs:annotation> 
    <xs:sequence> 
     <xs:element ref="tns:element" maxOccurs="unbounded"/> 
    </xs:sequence> 
    <xs:attribute name="number" type="tns:number"/> 
    <xs:assert test=" 
     every $id in ./@number satisfies 
     every $e in .//tns:element/@number satisfies 
     starts-with($e,$id)"> 
     <xs:annotation> 
     <xs:documentation> 
      Each element-identifying number has the 
      item-identifying number of the containing item 
      as a prefix. 
      Enforces constraint 5. 
     </xs:documentation> 
     </xs:annotation> 
    </xs:assert> 
    <xs:assert test=" 
     every $id in ./@number satisfies 
     every $e in .//tns:element/@number satisfies 
     string-length($e) = string-length($id) + 2"> 
     <xs:annotation> 
     <xs:documentation> 
      Each element-identifying number is two 
      digits longer than the item-identifying 
      number of the containing item. 
      Enforces constraint 6. 
     </xs:documentation> 
     </xs:annotation> 
    </xs:assert> 
    </xs:complexType> 

    <xs:complexType name="element" mixed="true"> 
    <xs:annotation> 
     <xs:documentation> 
     Each 'element' element has a 'number' attribute, 
     of type 'tns:number'. 
     (Enforces constraint 2 for 'element' elements.) 
     </xs:documentation> 
    </xs:annotation> 
    <xs:sequence/> 
    <xs:attribute name="number" type="tns:number"/> 
    </xs:complexType> 

    <xs:simpleType name="number"> 
    <xs:restriction base="xs:string"> 
     <xs:pattern value="\d+"/> 
    </xs:restriction> 
    </xs:simpleType> 
</xs:schema> 

注意每個XSD 1.1處理器需要支持的XPath 2.0的斷言一個相當最小的子集;我沒有努力試圖在這個子集中寫出斷言(但我也沒有做出任何努力來決定他們是否可以寫在那個子集中)。

有效的情況下,結構相同(據我可以告訴)到非XML例子:

<test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=" 
    http://example.com/elements-and-items 
    uniqueness.xsd" 
xmlns="http://example.com/elements-and-items"> 

    <item number="1"> 
    <element number="101"/> 
    <element number="102"/> 
    <element number="103"/> 
    </item> 
    <item number="2"> 
    <element number="201"/> 
    <element number="205"/> 
    <element number="206"/> 
    </item> 
    <item number="3"> 
    <element number="303"/> 
    <element number="301"/> 
    <element number="302"/> 
    </item> 

</test> 

無效的實例說明通過侵犯其每個約束;如果模式正在完成其工作,則應檢測到每個違規行爲並應使適當的元素或項目無效:

<test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=" 
    http://example.com/elements-and-items 
    uniqueness.xsd" 
xmlns="http://example.com/elements-and-items"> 

    <item number="1"> 
    <element number="101"/> 
    <element number="102"/> 
    <element number="103"/> 
    </item> 
    <item number="1"> 
    <!--* duplicate item number, invalid 
     * (violates constraint 3) 
     *--> 
    <element number="104"/> 
    <element number="105"/> 
    <element number="106"/> 
    </item> 
    <item number="2"> 
    <element number="107"> 
     element number unique but doesn't match item number 
     (violates constraint 5) 
    </element> 
    <element number="202"/> 
    <element number="202"> 
     item number not unique 
     (violates constraint 4) 
    </element> 
    </item> 
    <item number="3"> 
    <element number="303"/> 
    <element number="301"/> 
    <element number="3141592"> 
     item number unique and matches item number 
     but more than two digits longer 
     (violates constraint 6)</element> 
    </item> 

</test>