XSD-要素を任意の順序で何度でも許可するにはどうすればよいですか?


109

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をunboundedに設定しても、子要素の「任意の1つ」が複数回出現する可能性があるだけです。これは正確ですか?

上記の解決策が正しくない場合、要件で上記の内容をどのように達成できますか?

編集:要件が次のようになっている場合はどうなりますか?

  • 要素child1 child2は何度でも出現できます(0から無制限)
  • 要素を任意の順序にする
  • 要素child3およびchild4は1回だけ出現する必要があります。

たとえば、次の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>

回答:


61

質問のスキーマに、child1またはchild2任意の順序で、何度でも表示できます。だから、これはあなたが探しているもののように聞こえます。

編集:そのうちの1つだけを無制限に表示したい場合は、代わりに無制限の要素に移動する必要があります。

編集: XMLの固定型。

編集: maxOccursの大文字のO

<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>

基本的にはい、私は要素child1、child2を任意の順序で、何度も表示されるように探しています。それとも私の要件も解決しますか?
jvtech

質問のスキーマは要件を満たしています。私の答えの代替スキーマは単一の要素用です。これで問題が解決することを願っています。:)
xcut

@ Pavel、@ xcut、説明をありがとう、編集された要件を参照してください。
jvtech 2010

2
jvtech:XMLスキーマでは、編集された要件を満たすことができません。これを達成する唯一の方法は、child3とchild4が最後にしか表示できない場合です。その場合、選択肢と2つの要素を含むシーケンスが必要です。
xcut

1
@ Daij-Djan私もそれが機能しないことを発見しました。1つ以上の子要素が許可されるように、choice要素にmaxOccurs = "unbounded"を追加してみてください。
MikeD 2015年

107

後の編集で追加された質問の別の定式化はまだ回答されていないようです:要素の子の間に、child3という名前のchild4、のいずれchild1child2、またはのいずれかの番号があり、の順序に制約がないことを指定する方法子供たちが現れる。

これは直接定義可能な正規言語であり、必要なコンテンツモデルは、数字の「3」と「4」がそれぞれ1回だけ出現し、数字の「1」と「2」が現れる文字列のセットを定義する正規表現に同型です。 'は何度も発生します。これをどのように書くかが明らかでない場合は、そのような言語を認識するためにどのような有限状態マシンを構築するかについて考えることが役立つ場合があります。少なくとも4つの異なる状態があります。

  • 「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>

0個以上の選択肢を挿入する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>

我々はバルクを少し最小限にしたい場合は、我々はの繰り返しの選択肢のためにという名前のグループを定義することができますchild1し、child2

<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-groups に対するこれらの変更は、実際には言語の表現力を変更しません。特定の種類の言語の定義をより簡潔にするだけです。


3
私はXSD 1.0 xs:all代替が好きです。
TWiStErRob

8
+1。これは優れた答えであり、より多くの賛成投票に値します。
Christoffer Lette 2013年

1
すばらしい答えです!私はこのような説明が本当に好きです。それは、目標の達成の背後にあるすべての論理と推論を明らかにします。今、私はこの問題を解決する方法を知っているだけでなく、同様の問題を解決する新しいアプローチを学びました。有限状態自動化を使用してこれを説明することは非常に良い考えです。
egelev 2014

3
マイケル、あなたは「すべてのグループに対するこれらの変更は実際には言語の表現力を変更するのではなく、特定の種類の言語の定義をより簡潔にするだけである」と言います。しかし、問題を任意の数の子要素に一般化すると、そのサブセットは1回だけ出現し、別のサブセットは何度も出現する可能性がありますが、XSD 1.0ソリューションは組み合わせ爆発に発展しますね。XSD 1.1ソリューションはクリーンなままですが。
ebruchez 2014年

1
ebruchez、はい- 表現力は、私が用語を使用して、同じではない簡潔コンパクトさ簡潔さ、または管理。表現力は「この形式主義がこの言語を定義できるか」と尋ねるだけです。文法のサイズについて、または構文糖鎖によって文法を小さくするかどうかについては質問しません。あなたが言及している組み合わせの爆発は、すべてのグループに対するXSD 1.1の変更なしに要素の大きなセットを処理することが非常に不快で非常に速くなることを意味します(nが大きいとメモリを使い果たす可能性があります)。原則として不可能になるわけではありません。
CM Sperberg-McQueen 2014

49

これは最終的に私のために働いたものです:

<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>

5
実際の秘訣は、xsd:choiceと数量詞<xsd:choice minOccurs = "0" maxOccurs = "unbounded">を使用することです
tivo

6
上記の例は、choice-elementを囲むsequence-elementがなくても機能することを指摘する価値があると思います。

9

しかし、私が理解していることから、xs:choiceは依然として単一要素の選択しか許可していません。したがって、このようにMaxOccursをunboundedに設定しても、子要素の「任意の1つ」が複数回出現する可能性があるだけです。これは正確ですか?

いいえ。選択はxs:choice、が原因で発生する「繰り返し」ごとに個別に行われmaxOccurs="unbounded"ます。したがって、あなたが投稿したコードは正しいものであり、実際にあなたが書いたとおりにあなたが望むことを行います。


@Alanが提供する回答を含むコメントは、すべてをうまく説明しています。
BOR

3

次のスキーマは、提案したものを許可していることがわかります。

  <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>

あなたの質問に一致するようです。


minOccursmaxOccurs子供は1に制限されていxs:allます。
Pavel Minaev、2010

Pavel:ありがとう...私は自分の投稿をダブルチェックした後でこれを見つけ、それを編集してxs:allを削除しました
Steven_W

1

上記のいずれも機能していない場合は、おそらくEDIトランザクションに取り組んでおり、HIPPAスキーマまたはその他の複雑なxsdに対して結果を検証する必要があります。要件は、REFセグメントが8つあり、それらのいずれかが任意の順序で出現する必要があり、すべてが必須ではないということです。つまり、1番目のREF、3番目のREF、2番目のREF、9番目の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>

解決:

ここでは、単に「シーケンス」を「すべて」に置き換えるか、「選択」を最小/最大の組み合わせで使用しても機能しません。

まず最初に、次のように置き換え"xs:sequence" with "<xs:all>" ます。要素を参照している場所に変更を加える必要があります。

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

***上記のセグメントで、このように最後にトリガーポイントを最後に追加します。 "、" XX "、" YY "など。レコード情報は次のようになります。b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">


これにより、各要素が一意になります。理由は、すべてのREFセグメント(上記の例)がREF01、REF02、REF03のような同じ構造を持つためです。また、検証中に構造検証は問題ありませんが、最初のREF自体で残りの値を検索しようとするため、値を繰り返すことができません。トリガーを追加すると、トリガーがすべて一意になり、任意の順序で、状況に応じて渡されます(9/9のすべてではなく5から9を使用するなど)。

私がこれに20時間近く費やしたので、それがあなたを助けることを願っています。

幸運を

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.