После поиска в Интернете и поиска в некоторых книгах я понял, как это реализовать.
Прежде всего нам нужно определить универсальный тип, который вмещает все атрибуты и элементы обоих типов элемента примитив . Предполагается, что элемент definition определен где-то еще.
<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>
Затем мы определяем два примитива подтипов, которые будут использоваться в primitive-list , и
композит соответственно.
<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>
Давайте посмотрим на требования исходной схемы и посмотрим, как они применяются:
- Если элемент примитив указан внутри элемента primitive-list , то он должен содержать атрибут name и внедренное определение элемент, но не атрибут ref .
Это требование обеспечивается определением только публично-примитивного типа .
- Если элемент примитив указан в элементе составной , то он должен содержать либо атрибут ref , либо элемент definition, имя не допускается ни в одном из случаев.
Это требование обеспечивается определением типа private-primitive и элементом xs: key , указанным в элементе primitive , определенном внутри составной элемент. xs: key гарантирует, что присутствует ref или определение , но не оба.