使用属性和元素创建XML模式,具体取决于其他属性

时间:2009-10-21 11:33:13

标签: xml xsd

我正在尝试开发一个模式来验证我继承的一些现有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>

如果该生物的“类型”是“人类”,我将拥有“国籍”属性和“地址”子元素。如果该生物的“类型”是“动物”,我将拥有“物种”属性和“生境”子元素。出于这个例子的目的,具有“物种”或“栖息地”的“人”将是无效的 - 具有“国籍”或“地址”的“动物”也是如此。

如果“生物”不是根元素,我可能在根元素下面有两个不同的“生物”选择,但是当“生物”是根元素时,我不知道如何使这个工作。

是否有为这些仅匹配有效文档的文件创建架构?如果是这样,我该怎么做呢?

1 个答案:

答案 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>