4 つの解決策。そのうちのいくつかは、情報の XML 表現を再考することを伴います。
XSD 1.1 アサーション
説明したことを実行する最も簡単な方法は、XSD 1.1 を使用し、アサーションで念頭に置いている制約を定義することです。親要素が何と呼ばれているかは言いません。私はそれを支払いと呼びます。tns
そして、ターゲット名前空間のプレフィックスを使用します。
<xs:element name="Payment">
<xs:complexType>
<xs:sequence>
<xs:element ref="tns:PaymentMethod"/>
<xs:choice>
<xs:element ref="tns:ACHInfo" minOccurs="0"/>
<xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
</xs:choice>
</xs:sequence>
<xs:assert test="(tns:PaymentType = 'ACH' and ./tns:ACHInfo)
or
(tns:PaymentType = 'CreditCard'
and ./tns:CreditCardInfo)"/>
</xs:complexType>
</xs:element>
XSD 1.1 条件付き型の割り当て
目的によっては、Payment に条件付きの型割り当て (これも 1.1 の機能) を使用することをお勧めします。技術的な理由から、PaymentType を子ではなく Payment の属性にする必要があります。
<xs:element name="Payment">
<xs:alternative test="@PaymentMethod='ACH'"
type="tns:ACHPayment"/>
<xs:alternative test="@PaymentMethod='CreditCard'"
type="tns:CCPayment"/>
<xs:alternative type="xs:error"/>
</xs:element>
この宣言は、PaymentMethod 属性の値が「ACH」の場合、Payment 要素の型が tns:ACHPayment である (後で定義します) ことを意味します。それ以外の場合、PaymentMethod の値が「CreditCard」の場合、Payment のタイプは tns:CCPayment です。それ以外の場合、要素は無効です。
名前付き型 ACHPayment および CCPayment を適切な子を含む (および PaymentMethod 属性も提供する) と宣言します。
<xs:complexType name="ACHPayment">
<xs:sequence>
<xs:element ref="tns:ACHPayment"/>
</xs:sequence>
<xs:attribute name="PaymentMethod" type="tns:PaymentMethod"/>
</xs:complexType>
<xs:complexType name="CCPayment">
<xs:sequence>
<xs:element ref="tns:CreditCardPayment"/>
</xs:sequence>
<xs:attribute name="PaymentMethod" type="tns:PaymentMethod"/>
</xs:complexType>
同じ理由で、PaymentMethod 属性の型に名前付き宣言を提供します。
<xs:simpleType name="PaymentMethod">
<xs:restriction base="xs:string">
<xs:enumeration value="ACH"/>
<xs:enumeration value="CreditCard"/>
</xs:restriction>
</xs:simpleType>
XSD 1.0、支払い方法をコンテンツ モデルに移行
ただし、アプリケーションで機能する XML を作成するために XSD 1.1 は必要ありません。デザインについて別の方法で考える必要があるだけです。ACH の支払いには ACHinfo を必須にし、クレジット カードの支払いには CreditCardInfo を必須にするのは簡単です。コンテンツではなく要素の名前で支払いタイプの選択を行う場合です。親タイプを次のように定義する代わりに:
<xs:complexType>
<xs:sequence>
<xs:element ref="tns:PaymentMethod"/>
<xs:element ref="CreditCardInfo" minOccurs="0"/>
<xs:element ref="ACHInfo" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
次のように宣言できます。
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element ref="tns:ACHPayment"/>
<xs:element ref="tns:ACHInfo" minOccurs="0"/>
</xs:sequence>
<xs:sequence>
<xs:element ref="tns:CCPayment"/>
<xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
</xs:sequence>
</xs:choice>
</xs:complexType>
CCPayment と ACHPayment の 2 つのフラグ要素は、空の要素にすることができます。
<xs:complexType name="EMPTY">
<xs:sequence/>
</xs:complexType>
<xs:element name='ACHPayment' type="tns:EMPTY"/>
<xs:element name='CCPayment' type="tns:EMPTY"/>
しかし、現状では、これらのどちらも設計で機能していません。
XSD 1.0、簡素化
ACHPayment 要素も CCPayment 要素も、(a) 支払いがこの方法を使用することを通知し、(b) 次の兄弟が正しいことを確認する以上の作業を行っていない場合、どちらもまったく作業を行っていません。 .
親要素を次のように簡単に定義できます。
<xs:element name="Payment">
<xs:complexType>
<xs:choice>
<xs:element ref="tns:ACHInfo" minOccurs="0"/>
<xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
</xs:choice>
</xs:complexType>
</xs:element>
支払いが ACH 支払い (Payment 要素の子の名前は ACHInfo) であるか、クレジット カード支払い (子の名前は CreditCardInfo) であるかを引き続き確認でき、詳細情報が一致していることを確認する必要がなくなりました。 PaymentMethod フラグがなくなったため、PaymentMethod フラグ。
可動部品が減り、やるべきことが減り、失敗することも減ります。
この4つのデザインの中で、おそらくこの4つ目がベストだと思います。もちろん、走行距離は異なる場合があります。