XSD不同类型的同名

时间:2014-06-12 12:26:57

标签: xml xsd

您好我是XML / XSD的新手,所以对于大多数人来说这可能是一个简单的问题,但我无法找到解决问题的有效方法。

我有一个xml,如:

<?xml version="1.0" encoding="UTF−8"?>
<gallery>
  <character >
      <name>Luke Skywalker</name>
      <species>Human</species> 
      <language>Basic</language>
      <home>Tatooine</home>
  </character>
  <character >
      <name>Chewbacca</name>
      <species>Wookie</species>
      <language>Shyriiwook</language>
      <home>Kashyyyk</home>
      <battlecry>AARGH!</battlecry>
  </character>
</gallery>

它是一个画廊,第二个角色有额外的元素battlectry(它是一个wookie元素,另一个元素是starWars类型)

我有一个XSD,我定义了wookieType和starWarsEntity

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:complexType name="starWarsEntity">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="species" type="xsd:string"/>
            <xsd:element name="language" type="xsd:string"/>
            <xsd:element name="home" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="wookieType">
        <xsd:complexContent>
            <xsd:extension base="starWarsEntity">
                <xsd:sequence>
                    <xsd:element name="battlecry" type="xsd:string"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="character">
        <xsd:choice>
            <xsd:element name="wookieType" type="wookieType" />
            <xsd:element name="starWarsEntity" type="starWarsEntity"/>
        </xsd:choice>

    </xsd:complexType>

    <xsd:complexType name="gallery">
        <xsd:sequence>
            <xsd:element name="character" type="character" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>


    <xsd:element name="gallery" type="gallery">
    </xsd:element>


</xsd:schema>

我想要的是一个包含可以是wookyType或starWarsEntity类型的字符的画廊

我在link上在线验证了这两个文件你可以看到那两个文件,但是我收到了一些错误:

从元素'name'开始发现无效内容。预计会有一个'{wookieType,starWarsEntity}'。

我做错了什么,两个文件都有效?

2 个答案:

答案 0 :(得分:2)

您声明gallery包含character序列。这是对的。

但后来你声明character可以选择 <{em> <wookieType><starWarsEntity>。该错误表示character元素不能包含name元素,根据您的架构,这是正确的。

您在架构中声明它的方式,您的文档只会验证您是否使用它:

<gallery>
    <character >
        <starWarsEntity>
            <name>Luke Skywalker</name>
            <species>Human</species> 
            <language>Basic</language>
            <home>Tatooine</home>
        </starWarsEntity>
    </character>
    <character >
        <wookieType>
            <name>Chewbacca</name>
            <species>Wookie</species>
            <language>Shyriiwook</language>
            <home>Kashyyyk</home>
            <battlecry>AARGH!</battlecry>
        </wookieType>
    </character>
</gallery>

答案 1 :(得分:2)

您的验证者正在发出错误消息,告知您该文档无效;你为什么总结说“两个文件都有效?”?

您的架构说'character'元素可以包含两个孩子中的任何一个:starWarsEntitywookietype。如果要使XML对模式有效,可以将XML更改为:

<gallery>
  <character >
    <starWarsEntity>
      <name>Luke Skywalker</name>
      ...
    </starWarsEntity>
  </character>
  <character >
    <wookieType>
      <name>Chewbacca</name>
      ...
      <battlecry>AARGH!</battlecry>
    </wookieType>
  </character>
</gallery>

如果你想要一个接受你的XML的模式,一个更简单的方法就是定义character一个类型,其中battlecry是可选的:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:complexType name="character">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="species" type="xsd:string"/>
            <xsd:element name="language" type="xsd:string"/>
            <xsd:element name="home" type="xsd:string"/>
            <xsd:element name="battlecry" type="xsd:string" 
                         minOccurs="0"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="character" type="character"/>

    <xsd:complexType name="gallery">
        <xsd:sequence>
            <xsd:element ref="character" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="gallery" type="gallery"/>

</xsd:schema>

如果你想确保所有的怪物,只有怪物,有一个战斗,最简单的方法是区分怪物与其元素名称中的其他角色。我们假设wookie元素描述了wookie字符,'character'元素描述了非wookie字符。

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:complexType name="starWarsEntity">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="species" type="xsd:string"/>
            <xsd:element name="language" type="xsd:string"/>
            <xsd:element name="home" type="xsd:string"/>
            <xsd:element name="battlecry" type="xsd:string" 
                         minOccurs="0"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="wookie-character">
      <xsd:complexContent>
        <xsd:restriction base="starWarsEntity">
          <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="species" type="xsd:string">
              <xsd:simpleType>
                <xsd:restriction base="xsd:string">
                  <xsd:enumeration value="wookie">
                    <xsd:annotation>
                      <xsd:documentation>
                        For a wookie character, the species element conveys no new
                        information at all; we already know the character's species
                        from the name of the element.  But we retain the species
                        element in order to keep 'wookie' and 'character' parallel
                        in structure.
                      </xsd:documentation>
                    </xsd:annotation>
                  </xsd:enumeration>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="language" type="xsd:string"/>
            <xsd:element name="home" type="xsd:string"/>
            <xsd:element name="battlecry" type="xsd:string" 
              minOccurs="1"/>
          </xsd:sequence>
        </xsd:restriction>
      </xsd:complexContent>

    </xsd:complexType>

  <xsd:complexType name="non-wookie-character">
    <xsd:complexContent>
      <xsd:restriction base="starWarsEntity">
        <xsd:sequence>
          <xsd:element name="name" type="xsd:string"/>
          <xsd:element name="species">
            <xsd:simpleType>
              <xsd:restriction base="xsd:string">
                <xsd:pattern value="()|[^w].*|.[^o].*|..[^o].*|...[^k}.*|....[^i].*|.....[^e].*">
                  <xsd:annotation>
                    <xsd:documentation>
                      For a non-wookie character, we allow any species except 'wookie'.
                    </xsd:documentation>
                  </xsd:annotation>
                </xsd:pattern>
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
          <xsd:element name="language" type="xsd:string"/>
          <xsd:element name="home" type="xsd:string"/>
          <xsd:element name="battlecry" type="xsd:string" 
            maxOccurs="0"/>
        </xsd:sequence>
      </xsd:restriction>
    </xsd:complexContent>

  </xsd:complexType>

    <xsd:complexType name="gallery">
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="character" type="non-wookie-character"/>
          <xsd:element name="wookie" type="wookie-character"/>
        </xsd:choice>
    </xsd:complexType>

    <xsd:element name="gallery" type="gallery"/>

</xsd:schema>

XSD的核心设计根据其名称决定应用于元素的类型,可能由其祖先的名称和类型限定。如果您设计XML以使用该方法,而不是反对它,XSD将更容易使用。

在XSD 1.1中,可以使用断言来确保具有species ='wookie'的每个字符元素都具有battlecry,或者检查输入中的其他类型的冗余。但断言的可用性并不意味着违反DRY原则突然成为一个好主意。