インターネットで検索し、いくつかの本を掘り下げた後、それを実装する方法を見つけました。
まず、両方の種類のプリミティブ要素のすべての属性と要素に対応するジェネリック型を定義する必要があります。定義要素が別の場所で定義されていると想定されます。
<xs:complexType name="primitive" abstract="true">
<xs:sequence>
<xs:element ref="definition" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="name" type="xs:Name" />
<xs:attribute name="ref" type="xs:Name" />
</xs:complexType>
次に、プリミティブ リストと
コンポジットでそれぞれ使用する 2 つのプリミティブサブタイプを定義します。
<xs:complexType name="public-primitive">
<xs:complexContent>
<xs:restriction base="primitive">
<xs:sequence>
<xs:element ref="definition" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="name" type="xs:Name" use="required" />
<xs:attribute name="ref" use="prohibited" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="private-primitive">
<xs:complexContent>
<xs:restriction base="primitive">
<xs:sequence>
<xs:element ref="definition" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="name" use="prohibited" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
次のように、これらの複合型に関してプリミティブリストと複合要素を定義できます。
<xs:element name="primitive-list">
<xs:complexType>
<xs:sequence>
<xs:element name="primitive" type="public-primitive" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="composite">
<xs:complexType>
<xs:sequence>
<xs:element name="primitive" type="private-primitive" maxOccurs="unbounded">
<xs:key name="definition-ref--co-occurrence--constraint">
<xs:selector xpath="." />
<xs:field xpath="definition|@ref" />
</xs:key>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
元のスキーマ要件を見て、それらがどのように適用されるかを見てみましょう。
- プリミティブ要素がプリミティブ リスト要素内で指定されている場合、名前属性と埋め込み定義要素を含める必要がありますが、 ref属性は含めないでください。
この要件は、パブリック プリミティブ型の定義のみによって強制されます。
- プリミティブ要素が複合要素で指定されている場合、 ref属性または定義要素のいずれかが含まれている必要があります。どちらの場合も名前は許可されません。
この要件は、プライベート プリミティブ型の定義と、複合要素内で定義されたプリミティブ要素で指定されたxs:key要素によって強制されます。xs:keyは、 refまたはdefinitionのいずれかが存在することを保証しますが、両方は存在しません。