您好我是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}'。
我做错了什么,两个文件都有效?
答案 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'元素可以包含两个孩子中的任何一个:starWarsEntity
或wookietype
。如果要使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原则突然成为一个好主意。