簡體   English   中英

XSD - 如何允許任意順序的元素任意次數?

[英]XSD - how to allow elements in any order any number of times?

我正在嘗試創建一個 XSD,並嘗試編寫具有以下要求的定義:

  • 允許指定的子元素出現任意次數(0 到無界)
  • 允許子元素按任何順序排列

我環顧四周,發現了各種類似解決方案:

<xs:element name="foo">
  <xsl:complexType>
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="child1" type="xs:int"/>
      <xs:element name="child2" type="xs:string"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

但據我了解 xs:choice 仍然只允許選擇單個元素。 因此,像這樣將 MaxOccurs 設置為無界應該只意味着“任何一個”子元素可以出現多次。 這是准確的嗎?

如果上述解決方案不正確,我該如何實現上述要求?

編輯:如果要求如下怎么辦?

  • 元素 child1 child2 可以出現任意次數(0 到無界)
  • 元素以任何順序排列
  • 元素 child3 和 child4 應該只出現一次。

例如,這個 xml 是有效的:

<foo>
<child1> value </child1>
<child1> value </child1>
<child3> value </child3>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>

但這不是(缺少 child3)

<foo>
<child1> value </child1>
<child1> value </child1>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>

在稍后的編輯中添加的問題的替代表述似乎仍然沒有答案:如何指定在一個元素的子元素中,必須有一個名為child3 ,一個名為child4 ,以及任何名為child1child2的數字,沒有約束按照孩子出現的順序。

這是一種可直接定義的正則語言,您需要的內容模型與定義字符串集的正則表達式同構,其中數字“3”和“4”每個只出現一次,數字“1”和“2” ' 出現任意次數。 如果不清楚如何編寫它,那么考慮構建什么樣的有限狀態機來識別這種語言可能會有所幫助。 它至少有四種不同的狀態:

  • 既沒有看到“3”也沒有看到“4”的初始狀態
  • 看到“3”但沒有看到“4”的中間狀態
  • 看到“4”但沒有看到“3”的中間狀態
  • 已看到“3”和“4”的最終狀態

無論自動機處於何種狀態,都可以讀取“1”和“2”; 它們不會改變機器的狀態。 在初始狀態下,“3”或“4”也會被接受; 在中間狀態下,只接受“4”或“3”; 在最終狀態下,既不接受“3”也不接受“4”。 如果我們首先為我們的語言子集定義一個正則表達式,其中只有“3”和“4”出現,那么正則表達式的結構最容易理解:

(34)|(43)

要允許 '1' 或 '2' 在給定位置出現任意次數,我們可以插入(1|2)* (或[12]*如果我們的正則表達式語言接受該符號)。 在所有可用位置插入這個表達式,我們得到

(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*

將其轉換為內容模型很簡單。 基本結構等價於正則表達式(34)|(43)

<xsd:complexType name="paul0">
  <xsd:choice>
    <xsd:sequence>
      <xsd:element ref="child3"/>
      <xsd:element ref="child4"/>
    </xsd:sequence>
    <xsd:sequence>
      <xsd:element ref="child4"/>
      <xsd:element ref="child3"/>
    </xsd:sequence>
  </xsd:choice>
</xsd:complexType>

插入一個零個或多個child1child2的選擇很簡單:

<xsd:complexType name="paul1">
  <xsd:sequence>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
  </xsd:sequence>
</xsd:complexType>

如果我們想稍微減少體積,我們可以為child1child2的重復選擇定義一個命名組:

<xsd:group name="onetwo">
  <xsd:choice>
    <xsd:element ref="child1"/>
    <xsd:element ref="child2"/>
  </xsd:choice>   
</xsd:group>

<xsd:complexType name="paul2">
  <xsd:sequence>
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>  
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

在 XSD 1.1 中, all -groups 的一些約束已被解除,因此可以更簡潔地定義此內容模型:

<xsd:complexType name="paul3">
  <xsd:all>
    <xsd:element ref="child1" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child2" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child3"/>
    <xsd:element ref="child4"/>      
  </xsd:all>
</xsd:complexType>

但是從前面給出的例子可以看出, all組的這些變化實際上並沒有改變語言的表達能力; 它們只會使某些語言的定義更加簡潔。

在您的問題中的架構中, child1child2可以按任意順序出現任意次數。 所以這聽起來像你在找什么。

如果您只希望其中一個出現無限次,則 unbounded 將不得不繼續使用元素:

<xs:element name="foo">
   <xs:complexType>
     <xs:choice maxOccurs="unbounded">
       <xs:element name="child1" type="xs:int" maxOccurs="unbounded"/>
       <xs:element name="child2" type="xs:string" maxOccurs="unbounded"/>
     </xs:choice>
   </xs:complexType>
</xs:element>

這最終對我有用:

<xsd:element name="bar">
  <xsd:complexType>
    <xsd:sequence>
      <!--  Permit any of these tags in any order in any number     -->
      <xsd:choice minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="child1" type="xsd:string" />
        <xsd:element name="child2" type="xsd:string" />
        <xsd:element name="child3" type="xsd:string" />
      </xsd:choice>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

但據我了解 xs:choice 仍然只允許選擇單個元素。 因此,像這樣將 MaxOccurs 設置為無界應該只意味着“任何一個”子元素可以出現多次。 這是准確的嗎?

不會。對於由於maxOccurs="unbounded"而發生的xs:choice的每次“重復”,選擇都會單獨發生。 因此,您發布的代碼是正確的,並且實際上會按照您所寫的那樣做。

您應該會發現以下架構允許您提出的建議。

  <xs:element name="foo">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:choice>
          <xs:element maxOccurs="unbounded" name="child1" type="xs:unsignedByte" />
          <xs:element maxOccurs="unbounded" name="child2" type="xs:string" />
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

這將允許您創建一個文件,例如:

<?xml version="1.0" encoding="utf-8" ?>
<foo>
  <child1>2</child1>
  <child1>3</child1>
  <child2>test</child2>
  <child2>another-test</child2>
</foo>

這似乎符合你的問題。

如果以上都不起作用,您可能正在處理 EDI 交易,您需要根據 HIPPA 模式或任何其他復雜的 xsd 驗證您的結果。 要求是,假設有 8 個 REF 段,並且它們中的任何一個都必須以任何順序出現,也不是全部都是必需的,這意味着您可以按照以下順序 1st REF、3rd REF、2nd REF、9th REF 擁有它們。 默認情況下EDI接收會失敗,因為默認的復雜類型是

<xs:sequence>
  <xs:element.../>
</xs:sequence>

當您通過引用調用您的元素時,情況甚至更復雜,然后該元素在其原始位置本身就非常復雜。 例如:

<xs:element>
<xs:complexType>
<xs:sequence>
<element name="REF1"  ref= "REF1_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF2"  ref= "REF2_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF3"  ref= "REF3_Mycustomelment" minOccurs="0" maxOccurs="1">
</xs:sequence>
</xs:complexType>
</xs:element>

解決方案:

這里簡單地用“all”替換“sequence”或使用“choice”和最小/最大組合是行不通的!

首先將"xs:sequence" with "<xs:all>"現在,您需要在引用元素的位置進行一些更改,然后轉到:

<xs:annotation>
  <xs:appinfo>
    <b:recordinfo structure="delimited" field.........Biztalk/2003">

***現在在上面的段中添加觸發點,像這樣 trigger_field="REF01_...complete name.." trigger_value = "38" 對觸發值不同的其他 REF 段執行相同的操作,比如說 "18 ", "XX" , "YY" 等等..這樣你的記錄信息現在看起來像: b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">


這將使每個元素都是唯一的,原因是所有 REF 段(上例)具有相同的結構,如 REF01、REF02、REF03。 在驗證過程中,結構驗證是可以的,但它不會讓值重復,因為它會嘗試在第一個 REF 本身中查找剩余值。 添加觸發器將使它們都是唯一的,並且它們將以任何順序和情境情況傳遞(例如使用 5 out 9 而不是全部 9/9)。

希望它對你有所幫助,因為我花了將近 20 個小時在這上面。

祝你好運

如果您的子元素很少,那么您可以在 <xs:choice> 中列出所有可能的序列。 這為每個序列提供了您想要的靈活性。 作為N! 增長非常迅速,這只適合最多 4 個子元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM