在互联网上搜索并挖掘了一些书籍后,我想出了如何实现它。
首先,我们需要定义一个泛型类型,它可以容纳来自两种原始元素的所有属性和元素。假设定义元素是在其他地方定义的。
<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>
然后我们定义两个原始子类型分别用于原始列表和
复合。
<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>
让我们看一下原始模式要求,看看它们是如何执行的:
- 如果在原始列表元素中指定了原始元素,则它应该包含name属性和嵌入的定义元素,但不包含ref属性。
此要求仅由public-primitive类型的定义强制执行。
- 如果在复合元素中指定了原始元素,则它应该包含ref属性或定义元素。在这两种情况下都不允许使用该名称。
此要求由私有原始类型的定义和在复合元素内部定义的原始元素中指定的xs:key元素强制执行。xs:key保证ref或定义都存在,但不能同时存在。