XML スキーマ (XSD) を定義するときに「グループ」要素を「選択」することは有効ですか?
質問
XML スキーマ (XSD) を定義するときに「choice」要素または「group」要素を使用することは有効ですか?
つまり次は有効ですか
<xs:complexType name="HeaderType">
<xs:sequence>
<xs:element name="reservation-number" type="ReservationNumberType" minOccurs="1" maxOccurs="1" nillable="false" />
<xs:choice minOccurs="1" maxOccurs="1">
<xs:group ref="ReservationGroup" />
<xs:group ref="CancellationGroup"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
XML メッセージは、たとえば、新しい予約または既存の予約のキャンセルを表すことができます。
メッセージが予約に関するものである場合、そのメッセージには、RegistrationGroup グループで定義されているすべての要素が含まれている必要があります。
キャンセルの場合は、CancelGroup グループで定義されたすべての要素を含める必要があります。
何らかの理由で、私の XML エディター (Eclipse) はこれを好みませんが、その理由は示されていません。<xs:complexType name="HeaderType"> 行にエラーがあることが示されていますが、エラーの内容は示されていません。
解決
私は XML の専門家ではありませんが、よく使用します。これは、私が通常この種の構造を行う方法ではありません。2 つのグループを選択するのではなく、別々の複合タイプを選択したいと思います (この回答の最後を参照)。
問題は、予約グループとキャンセルグループが同じ要素で始まることだと思います。その場合、スキーマコンポーネントの制約に違反します。ユニークなパーティクルの属性 (下)。
http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/#cos-nonambig
スキーマコンポーネントの制約:ユニークな粒子の帰属
コンテンツモデルは、要素情報項目シーケンスの検証中、粒子コンポーネントが直接、間接的に、または暗黙的にを含むように形成する必要があります。そのアイテムのコンテンツや属性を調べることなく、残りのシーケンスのアイテムに関する情報はありません。
注記: この制約は、XMLスキーマの[XML 1.0(第2版)]およびSGMLの同等の制約を再構築します。元素置換グループとワイルドカードの存在を考えると、この制約の簡潔な表現は困難です。詳細な議論のために、一意の粒子属性制約(非正規)(§H)の分析を参照してください。
たとえば、以下の 2 つのグループは同じ選択では無効です。その最初の要素はそれぞれ「名前」であり、どのグループを見ているのかを識別できないことを意味します。ただし、予約の最初の要素は、キャンセルグループ(resdate and Cancdateかもしれない)とは異なり、それは有効です。
編集: 私はこれまでこの種の問題に遭遇したことがありませんでした。グループの定義が完全に合法であるのは興味深いことだと思いますが、グループを 1 つの選択肢にまとめると、各グループの定義によりその選択が違法になります。
法的選択を形成できないグループ
<xs:group name="ReservationGroup">
<xs:sequence>
<xs:element name="date"/>
<xs:element name="name"/>
<xs:element name="address"/>
</xs:sequence>
</xs:group>
<xs:group name="CancellationGroup">
<xs:sequence>
<xs:element name="date"/>
<xs:element name="name"/>
<xs:element name="address"/>
</xs:sequence>
</xs:group>
法的選択を形成できるグループ
<xs:group name="ReservationGroup">
<xs:sequence>
<xs:element name="resDate"/>
<xs:element name="name"/>
<xs:element name="address"/>
</xs:sequence>
</xs:group>
<xs:group name="CancellationGroup">
<xs:sequence>
<xs:element name="cancDate"/>
<xs:element name="name"/>
<xs:element name="address"/>
</xs:sequence>
</xs:group>
上で述べたように、私はこの種のことを複合型で行います。はい、それは別の要素を追加しますが、それは明白な方法のように思えますし、私は明白さが好きです。
<xs:complexType name="HeaderType">
<xs:sequence>
<xs:element name="reservation-number" type="ReservationNumberType" minOccurs="1" maxOccurs="1" nillable="false" />
<xs:choice minOccurs="1" maxOccurs="1">
<xs:element name="reservation" type="ReservationType" />
<xs:element name="cancellation" type="CancellationType" />
</xs:choice>
</xs:sequence>
</xs:complexType>
他のヒント
はい。これは、予約グループとキャンセルグループの両方に同じ最初の要素、つまり、予約グループの「予約」とキャンセルグループの「キャンセル」という固定値を持つ「予約タイプ」要素があったためです。
これが有効かどうかは、グループの内容によって異なります。それらが「シーケンス」または「選択」モデル グループである場合、それは完全に合法です。「すべて」のモデル グループはさらに問題が多く、この場合は通常許可されません。