2014-03-05 201 views
1

我希望我的XSD能夠強制執行一組元素中至少有一個元素必須存在。其中一些元素可能出現無限次,有些是有限的。至少有一個這些元素,但最多隻有一個

這些元素本身都不是強制性的,但至少有一個元素必須存在。

最後,元素可以按任意順序出現。即爲了既不應強制執行,也不對文件的處理有任何影響

我嘗試這個:

<xs:element name="Root"> 
    <xs:complexType> 
    <xs:choice> 
     <xs:element minOccurs="0" maxOccurs="unbounded" name="A" type="a:a"/> 
     <xs:element minOccurs="0" maxOccurs="unbounded" name="B" type="a:a"/> 
     <xs:element minOccurs="0" maxOccurs="1" name="C" type="a:a"/> 
     <xs:element minOccurs="0" maxOccurs="1" name="D" type="a:a"/> 
    </xs:choice> 
    </xs:complexType> 
</xs:element> 

這並不完全工作,因爲它不執行有至少是一個的這些元素。

因此,在上面的例子中,必須有A,B,C或D. 中的至少一個可以有多個A或B的元素,但只有1各自爲C或d

所以下面的所有應有效:

  • <root><A/></root>
  • <root><A/><A/></root>
  • <root><A/><B/><A/></root>
  • <root><C/></root>
  • <root><D/><C/></root>

但是下面應該是無效的:

  • <root/> - 至少一個元素必須存在
  • <root></root> - 至少一個元素必須存在
  • <root><C/><C/></root> - 重複<C/>元素

有一個額外的複雜因素,這是對現有複雜類型的擴展,但我不認爲這會影響任何東西?

這可能嗎?

我嘗試添加minOccurs =「1」到xs:choice元素。這沒有效果,大概是因爲每個選擇的實例都可以是空的!我也試過有一個xs:choice(沒有minOccurs在子項中)和一個xs:序列(沒有C & D節點)但我找不到任何父元素,它們可以共存。

回答

1

除了允許前兩個應該是無效的示例外,您顯示的內容模型也失敗了,因爲不允許第三個或第五個應該是確定的示例。

到目前爲止,捕獲XSD,Relax NG或DTD中描述的約束條件的最簡單方法是添加另一個約束條件。然後內容模型(以DTD表示法)((A+, B*, C?, D) | (B+, C?, D?) | (C, D?) | (D))。如果A,B,C,D兒童的序列沒有傳達任何信息,這是迄今爲止最簡單的方法。

但是,如果孩子的順序確實傳達了信息,並且需要自由,那麼您的任務就非常複雜。不是特別困難,但很複雜,有時(特別是對於更復雜的例子)相當乏味。

您描述的A,B,C和D兒童的合法序列集合是一種常規語言;它可能有助於思考你將用來識別它的有限狀態自動機。基本上,你需要記錄三個信息:(a)我們是否看到過任何子元素? (b)我們看到過C元素嗎? (c)我們看到過D元素嗎?如果這些完全獨立,我們需要FSA中的八個州;因爲它們不是,我們只有五個需要:

  • 0開始狀態(無,不,不)
  • 1所看到的一個或多個A或B元素,但不是C或d(是,否,否)
  • 2都看到一個C元件,沒有d(X,是,否)
  • 3見過d元件,沒有C
  • 4所看到的C和d

的轉換表是

  • 0 A,B - > 1; C - > 2; D - > 3
  • 1 A,B - > 1; C - > 2; D→3
  • 2 A,B→2; C - >錯誤; D→4
  • 3 A,B→3; C - > 4; D - >錯誤
  • 4 A,B - > 4; C,D - >錯誤

接受狀態是1-4。

請注意,一旦我們看到至少一個元素,A和B都不會對自動機的狀態產生任何影響。這表明開始編寫內容模型的一種好方法是:忽略A和B一會兒,然後用C和D編寫一個內容模型。由於其中一個必須發生,但都不能重複,所以我們可以描述C的合法序列和d元素這樣(再次,在DTD符號爲緊湊):

((C, D?) | (D, C?)) 

允許A和B出現任意多次(而不是在序列的開始)給了我們

((C, (A|B)*, (D, (A|B)*)?) 
| (D, (A|B)*, (C, (A|B)*)?)) 

如果我們以A或B開始,As和Bs的初始序列可以跟隨任何與上述序列匹配的序列,或者不加任何東西。對於這種情況,內容模型是

((A|B)+, ((C, (A|B)*, (D, (A|B)*)?) 
     | (D, (A|B)*, (C, (A|B)*)?))?) 

把這些共同的內容模型作爲一個整體變得

(((A|B)+, ((C, (A|B)*, (D, (A|B)*)?) 
      | (D, (A|B)*, (C, (A|B)*)?))?) 
| (C, (A|B)*, (D, (A|B)*)?) 
| (D, (A|B)*, (C, (A|B)*)?)) 

是微不足道的翻譯成XSD符號此。

在某些模式語言中,更方便(大多數人認爲:更緊湊)表示這種或相關內容模型的方式。

Schematron或XSD 1。1,你可以寫斷言(使用XPath)說

  • 每個孩子都被命名爲A,B,C或D.
  • 至少有一個孩子。
  • 有一個名爲C.
  • 至多有一個孩子有一個名爲D.

在XSD 1.1最多隻有一個孩子,你可以使用所有組,其子女是A *,B *, C?和D?以及一個斷言說至少有一個孩子。

在RELAX NG,你可以寫一個內容模型,它允許空序列,但在其他方面如使用交錯式的操作說明,即:

(A* & B* & C? & D?) 

可以實施非空虛一個稍微更復雜的模型:

(((A|B), (A* & B* & C? & D?)) 
| (C, (A* & B* & D?)) 
| (D, (A* & B* & C?))) 
+0

哇。感謝您的非常詳細的答案。 不幸的是,我不熟悉DTD語法,但是如果我假設它有點類似於正則表達式,那麼我可以理解你在這裏有什麼。 只是爲了澄清一些事情 - 在我的例子中,元素的順序是完全不相關的。訂單不應受到限制,也不會以任何方式影響文檔的處理。父元素本質上是一個混雜的東西 – DJL

+0

我確實考慮過用所有可能的命令複製組的想法。然而,這對於4種元素類型來說同樣困難 - 在我的現實世界中,實際上有5種元素,這種情況幾乎肯定會增加。因此這不是一個實際的解決方案 - 絕對需要更通用的東西! – DJL

+1

是的,除了使用逗號而不是並置來描述序列之外,DTD符號類似於常規正則表達式的(的一個子集)。 –

相關問題