在下面的示例xml / xsd中,当用户输入AnimalCategories的值时,我希望AnimalBreeds中的枚举仅允许适当的值。例如,如果用户输入Cat,那么AnimalBreeds的有效选项应该只是Siamese和Persian。我已经查看了关于xsd 1.1中可用的断言和替代方案的帖子,但我无法看到如何将其应用于我的特定需求。
非常感谢任何想法。
<?xml version="1.0" encoding="UTF-8"?>
<AnimalsData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="AnimalsData.xsd">
<AnimalData AnimalCategories="Dog" AnimalBreeds="Boxer"/>
<AnimalData AnimalCategories="Cat" AnimalBreeds="Siamese"/>
</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: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>
答案 0 :(得分:4)
如果您可以枚举类别及其品种,那么使此类可检查的最简单方法是使用类别名称(以及可选的品种)作为元素名称,而不是属性值。
如果您只针对类别而非品种执行此操作,则您的XML可能采用以下格式:
<AnimalsData>
<Dog Breeds="Boxer"/>
<Cat Breeds="Siamese"/>
</AnimalsData>
Dog和Cat的元素可以替代AnimalData(您可能希望将其作为摘要,除非您期望某些非狗,非cat实例;您当前的架构表示您不期望任何此类),以及它们的类型源自AnimalData。对于狗,必要的机械看起来像这样:
<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"/>
Cat以同样的方式工作。当然,由于属性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
和Cat
);为了限制品种,您还需要特定类别的AnimalBreedsType
子类型。然后在xs:alternative
的元素声明中使用AnimalData
为元素指定正确的限制类型。整个架构看起来像这样。 (我已将这两个属性设为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>
请注意,所有这四种变体都编码有关类别和品种之间相关性的相同信息,但在某些情况下,其他软件比其他软件更容易获取这些信息。
答案 1 :(得分:1)
如果您想使用其他类型,可以在下面找到另一个架构示例。
<?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:complexType>
<xs:complexType name="DogDataType">
<xs:complexContent>
<xs:extension base="AnimalDataType">
<xs:attribute name="AnimalBreeds" type="DogBreedsType" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CatDataType">
<xs:complexContent>
<xs:extension base="AnimalDataType">
<xs:attribute name="AnimalBreeds" type="CatBreedsType" use="required"/>
</xs:extension>
</xs:complexContent>
</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="DogBreedsType">
<xs:restriction base="xs:string">
<xs:enumeration value="Boxer"/>
<xs:enumeration value="Rottweiler"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="CatBreedsType">
<xs:restriction base="xs:string">
<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:alternative test="@AnimalCategories='Dog'" type="DogDataType"/>
<xs:alternative test="@AnimalCategories='Cat'" type="CatDataType"/>
</xs:element>
<xs:attribute name="AnimalCategories" type="AnimalCategoriesType"/>
</xs:schema>