我正在尝试开发一个模式来验证我继承的一些现有XML文件。我希望模式能够尽可能多地完成验证工作。挑战在于属性和元素取决于其他属性的值。
真实数据非常抽象,所以我创建了一些简单的例子。假设我有以下XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<Creature type="human" nationality="British">
<Address>London</Address>
</Creature>
<?xml version="1.0" encoding="UTF-8"?>
<Creature type="animal" species="Tiger">
<Habitat>Jungle</Habitat>
</Creature>
如果该生物的“类型”是“人类”,我将拥有“国籍”属性和“地址”子元素。如果该生物的“类型”是“动物”,我将拥有“物种”属性和“生境”子元素。出于这个例子的目的,具有“物种”或“栖息地”的“人”将是无效的 - 具有“国籍”或“地址”的“动物”也是如此。
如果“生物”不是根元素,我可能在根元素下面有两个不同的“生物”选择,但是当“生物”是根元素时,我不知道如何使这个工作。
是否有为这些仅匹配有效文档的文件创建架构?如果是这样,我该怎么做呢?
答案 0 :(得分:7)
您可以为此目的使用xsi:type属性(您必须使用XMLSchema实例命名空间中的xsi:type而不是您自己的命名空间,否则它将无法工作)。
在模式中,您声明一个声明为抽象的基类型,并为每个子类型创建其他复杂类型(具有特定于该类型的元素/属性)。
请注意,虽然此解决方案有效,但最好为每种类型使用不同的元素名称(xsi:type有点违背格式,因为它现在是type属性与定义的元素名称的组合类型而不仅仅是元素名称。)
例如:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Creature" type="CreatureType">
</xs:element>
<xs:complexType name="CreatureType" abstract="true">
<!-- any common validation goes here -->
</xs:complexType>
<xs:complexType name="Human">
<xs:complexContent>
<xs:extension base="CreatureType">
<xs:sequence maxOccurs="1">
<xs:element name="Address"/>
</xs:sequence>
<xs:attribute name="nationality" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Animal">
<xs:complexContent>
<xs:extension base="CreatureType">
<xs:sequence maxOccurs="1">
<xs:element name="Habitat"/>
</xs:sequence>
<xs:attribute name="species" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
此架构将验证这两个:
<?xml version="1.0" encoding="UTF-8"?>
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="Human"
nationality="British">
<Address>London</Address>
</Creature>
<?xml version="1.0" encoding="UTF-8"?>
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="Animal"
species="Tiger">
<Habitat>Jungle</Habitat>
</Creature>
但不是这样:
<?xml version="1.0" encoding="UTF-8"?>
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="SomeUnknownThing"
something="something">
<Something>Something</Something>
</Creature>
或者这个:
<?xml version="1.0" encoding="UTF-8"?>
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="Human"
species="Tiger">
<Habitat>Jungle</Habitat>
</Creature>