如果您可以枚举类别及其品种,最简单的方法是使用类别名称(以及可选的品种)作为元素名称,而不是属性值。
如果您只为类别而不是品种执行此操作,则您的 XML 可能采用如下形式:
<AnimalsData>
<Dog Breeds="Boxer"/>
<Cat Breeds="Siamese"/>
</AnimalsData>
元素 Dog 和 Cat 可替代 AnimalData (您可能希望将其抽象化,除非您期望一些非狗、非猫实例;您当前的模式表明您不期望任何此类),并且它们的类型派生自动物数据的那个。对于 Dog,必要的机器如下所示:
<xs:complexType name="Dog">
<xs:complexContent>
<xs:restriction base="AnimalDataType">
<xs:attribute name="AnimalBreeds"
use="required"
type="DogBreedsType"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="DogBreedsType">
<xs:restriction base="AnimalBreedsType">
<xs:enumeration value="Boxer"/>
<xs:enumeration value="Rottweiler"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Dog" type="Dog" substitutionGroup="AnimalData"/>
猫的工作方式相同。当然,由于 AnimalCategories 属性现在与元素类型名称是多余的,因此我们将其删除:
<xs:complexType name="AnimalDataType">
<xs:attribute name="AnimalBreeds" use="required"
type="AnimalBreedsType"/>
</xs:complexType>
更彻底的重新思考也将品种从属性值转移到元素名称。XML 将如下所示:
<AnimalsData>
<Dog><Boxer/></Dog>
<Cat><Siamese/></Cat>
</AnimalsData>
架构看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
vc:minVersion="1.1">
<xs:complexType name="AnimalsDataType">
<xs:sequence>
<xs:element ref="AnimalData" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="AnimalDataType">
<xs:sequence>
<xs:element ref="Breed"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Dog">
<xs:complexContent>
<xs:restriction base="AnimalDataType">
<xs:sequence>
<xs:element ref="CanineBreed"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Cat">
<xs:complexContent>
<xs:restriction base="AnimalDataType">
<xs:sequence>
<xs:element ref="FelineBreed"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:element name="AnimalsData" type="AnimalsDataType"/>
<xs:element name="AnimalData" type="AnimalDataType" abstract="true"/>
<xs:element name="Dog" type="Dog" substitutionGroup="AnimalData"/>
<xs:element name="Cat" type="Cat" substitutionGroup="AnimalData"/>
<xs:element name="Breed" abstract="true">
<xs:complexType><xs:sequence/></xs:complexType>
</xs:element>
<xs:element name="CanineBreed" abstract="true"
substitutionGroup="Breed"/>
<xs:element name="FelineBreed" abstract="true"
substitutionGroup="Breed"/>
<xs:element name="Boxer" substitutionGroup="CanineBreed"/>
<xs:element name="Rottweiler" substitutionGroup="CanineBreed"/>
<xs:element name="Siamese" substitutionGroup="FelineBreed"/>
<xs:element name="Persian" substitutionGroup="FelineBreed"/>
</xs:schema>
要使用条件类型,请定义特定于类别的子类型AnimalDataType
(在下面的示例中,它们是Dog
and Cat
);要限制品种,您还需要特定类别的AnimalBreedsType
. 然后xs:alternative
在元素声明中使用 forAnimalData
为元素分配正确的受限类型。整个架构看起来像这样。(我将这两个属性设置为本地属性,AnimalData
因为让它们成为全局属性让我感到困惑。)
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
vc:minVersion="1.1">
<xs:complexType name="AnimalsDataType">
<xs:sequence>
<xs:element ref="AnimalData" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="AnimalDataType">
<xs:attribute ref="AnimalCategories" use="required"/>
<xs:attribute ref="AnimalBreeds" use="required"/>
</xs:complexType>
<xs:simpleType name="AnimalCategoriesType">
<xs:restriction base="xs:string">
<xs:enumeration value="Dog"/>
<xs:enumeration value="Cat"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="AnimalBreedsType">
<xs:restriction base="xs:string">
<xs:enumeration value="Boxer"/>
<xs:enumeration value="Rottweiler"/>
<xs:enumeration value="Siamese"/>
<xs:enumeration value="Persian"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="AnimalsData" type="AnimalsDataType"/>
<xs:element name="AnimalData" type="AnimalDataType"/>
<xs:attribute name="AnimalCategories" type="AnimalCategoriesType"/>
<xs:attribute name="AnimalBreeds" type="AnimalBreedsType"/>
</xs:schema>
要使用断言,只需将以下断言添加到声明中即可AnimalDataType
:
<xs:complexType name="AnimalDataType">
<xs:attribute ref="AnimalCategories" use="required"/>
<xs:attribute ref="AnimalBreeds" use="required"/>
<xs:assert test="if (@AnimalCategories='Dog')
then @AnimalBreeds = ('Boxer', 'Rottweiler')
else true()"/>
<xs:assert test="if (@AnimalCategories='Cat')
then @AnimalBreeds = ('Siamese', 'Persian')
else true()"/>
</xs:complexType>
请注意,所有这四种变体都编码了有关类别和品种之间相关性的相同信息,但在某些情况下,其他软件比其他软件更容易访问这些信息。