代码之家  ›  专栏  ›  技术社区  ›  dommer

创建属性和元素依赖于其他属性的XML架构

  •  9
  • dommer  · 技术社区  · 15 年前

    我正在尝试开发一个模式来验证我继承的一些现有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 回复  |  直到 15 年前
        1
  •  7
  •   Martin Wickett    15 年前

    为此,您可以使用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>