我有一个XML Schema,它描述了一个XML实例,其中<item>
元素包含其他元素,例如:
tariffs
category
director
tag
country
year
genre
这些元素可以以任意顺序出现。我必须在我的XSD中说明它们可能以随机顺序出现。
我读到需要使用<xs:all>
,但我无法使其工作。
这是我的XML实例:
<videos>
<item id="17314" description="Жизнь харизматичного ... жемчужины" age-limit="12">
<tariffs>
<tariff id="2" type-id="1" type-alias="subscription" price="179" duration="30"/>
<tariff id="6" type-id="2" type-alias="purchase" price="79" duration="30"/>
</tariffs>
<category id="71" title="Фильмы"/>
<director id="27449" title="Гор Вербински"/>
<tag id="752" title="пираты"/>
<tag id="894" title="любовь"/>
<tag id="1164" title="флот"/>
<tag id="1789" title="море"/>
<tag id="1790" title="сокровища"/>
<tag id="1811" title="нечисть"/>
<tag id="2292" title="похищение"/>
<tag id="2608" title="остров"/>
<tag id="2646" title="капитан"/>
<tag id="2999" title="проклятие"/>
<tag id="5944" title="магия"/>
<tag id="9888" title="18 век"/>
<tag id="13539" title="тайна"/>
<tag id="16045" title="спасение"/>
<tag id="18576" title="12+"/>
<country id="515" title="США"/>
<year id="227" title="2003"/>
<genre id="674" title="художественное"/>
<genre id="690" title="боевик"/>
<genre id="702" title="приключения"/>
<genre id="5938" title="фэнтези"/>
<genre id="6467" title="фестивальное"/>
<genre id="8964" title="HD фильмы"/>
</item>
<item id="15922" description="Супермодель ... один шаг." duration="89" url="http://www.tvzavr.ru/Svadba-po-obmenu" type="Single" rates="2" rating="6" ratesum="11" views="39331" topic="20584" seo-alias="Svadba-po-obmenu" requires_subscription="No" geo-limit="RU" name="Свадьба по обмену" age-limit="16">
<category id="71" title="Фильмы"/>
<director id="2264" title="Дмитрий Грачев"/>
<tag id="894" title="любовь"/>
<tag id="2384" title="месть"/>
<tag id="2425" title="телевидение"/>
<tag id="6156" title="Россия"/>
<tag id="9582" title="современность"/>
<tag id="9598" title="16+"/>
<tag id="13556" title="супруги"/>
<tag id="15526" title="обман"/>
<tag id="15984" title="ссора"/>
<country id="122" title="Россия"/>
<year id="234" title="2010"/>
<genre id="674" title="художественное"/>
<genre id="697" title="комедия"/>
<genre id="698" title="мелодрама"/>
</item>
<item id="16274" description="Жил-был ... арабской сказке." duration="95" url="http://www.tvzavr.ru/Iznougud-ili-Kalif-na-chas" type="Single" rates="2" rating="6" ratesum="11" views="14751" topic="21192" seo-alias="Iznougud-ili-Kalif-na-chas" requires_subscription="No" geo-limit="KZ BY RU" name="Изноугуд или Калиф на час" age-limit="12">
<category id="71" title="Фильмы"/>
<director id="25913" title="Патрик Брауде"/>
<tag id="894" title="любовь"/>
<tag id="2323" title="средневековье"/>
<tag id="2716" title="волшебство"/>
<tag id="9890" title="Восток"/>
<tag id="13617" title="рабство"/>
<tag id="15985" title="прислуга"/>
<tag id="18576" title="12+"/>
<country id="2543" title="Франция"/>
<year id="229" title="2005"/>
<genre id="674" title="художественное"/>
<genre id="697" title="комедия"/>
</item>
<item id="9660" description="Забавные ... развлечения!" duration="546" url="http://www.tvzavr.ru/Oazis-Oskara" type="Set" rates="90" rating="5" ratesum="412" views="2898560" topic="12826" seo-alias="Oazis-Oskara" requires_subscription="No" geo-limit="RU UA BY KZ AZ AM KG UZ TM TJ MD IN KR US PL DE" name="Оазис Оскара" age-limit="0">
<category id="678" title="Мультфильмы"/>
<director id="16910" title="Тае Сик Шин"/>
<director id="16911" title="Фредерик Мартин"/>
<director id="16912" title="Сильвейн Бойдо"/>
<tag id="2774" title="собака"/>
<tag id="5128" title="пустыня"/>
<tag id="7104" title="друзья"/>
<tag id="9558" title="зверушки"/>
<tag id="13586" title="волки"/>
<tag id="13606" title="погоня"/>
<tag id="15473" title="испытание"/>
<tag id="15706" title="птицы"/>
<tag id="15988" title="еда"/>
<country id="2543" title="Франция"/>
<year id="10996" title="2011"/>
<genre id="694" title="детское/семейное"/>
<genre id="702" title="приключения"/>
<genre id="9572" title="для дошкольников"/>
<genre id="9573" title="для школьников"/>
</item>
<item id="10366" description="Милый ... фильмов." duration="468" url="http://www.tvzavr.ru/Bernard" type="Set" rates="87" rating="5" ratesum="416" views="3885650" topic="13610" seo-alias="Bernard" requires_subscription="No" geo-limit="RU UA BY KZ AZ AM KG UZ TM TJ MD IN KR US PL DE" name="Бернард" age-limit="0">
<category id="678" title="Мультфильмы"/>
<director id="17936" title="Хосе Луис Уча"/>
<tag id="72" title="автомобили"/>
<tag id="98" title="футбол"/>
<tag id="1789" title="море"/>
<tag id="6338" title="неудачник"/>
<tag id="7104" title="друзья"/>
<tag id="9558" title="зверушки"/>
<tag id="10407" title="спортсмены"/>
<tag id="13606" title="погоня"/>
<tag id="15246" title="соперничество"/>
<tag id="15289" title="труд"/>
<tag id="15706" title="птицы"/>
<tag id="15988" title="еда"/>
<tag id="16028" title="опасность"/>
<country id="2543" title="Франция"/>
<country id="2600" title="Испания"/>
<country id="8789" title="Южная Корея"/>
<year id="228" title="2004"/>
<genre id="694" title="детское/семейное"/>
<genre id="702" title="приключения"/>
<genre id="9572" title="для дошкольников"/>
<genre id="9573" title="для школьников"/>
</item>
</videos>
这是一个XSD验证上面的文件,但没有满足我的需求,因为它强制执行元素的排序。
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="videos">
<xs:complexType>
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="tariffs" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="tariff" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:int" name="id" use="required"/>
<xs:attribute type="xs:int" name="type-id" use="required"/>
<xs:attribute type="xs:string" name="type-alias" use="required"/>
<xs:attribute type="xs:short" name="price" use="required"/>
<xs:attribute type="xs:int" name="duration" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="category" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="id" use="optional"/>
<xs:attribute type="xs:string" name="title" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="director" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="id" use="optional"/>
<xs:attribute type="xs:string" name="title" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="tag" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="id" use="optional"/>
<xs:attribute type="xs:string" name="title" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="country" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="id" use="optional"/>
<xs:attribute type="xs:string" name="title" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="year" maxOccurs="1" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="id" use="optional"/>
<xs:attribute type="xs:short" name="title" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="genre" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="id" use="optional"/>
<xs:attribute type="xs:string" name="title" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:short" name="id" use="optional"/>
<xs:attribute type="xs:string" name="name" use="optional"/>
<xs:attribute type="xs:string" name="type" use="optional"/>
<xs:attribute type="xs:string" name="requires_subscription" use="optional"/>
<xs:attribute type="xs:byte" name="age-limit" use="optional"/>
<xs:attribute type="xs:string" name="geo-limit" use="optional"/>
<xs:attribute type="xs:string" name="url" use="optional"/>
<xs:attribute type="xs:string" name="description" use="optional"/>
<xs:attribute type="xs:int" name="views" use="optional"/>
<xs:attribute type="xs:int" name="topic" use="optional"/>
<xs:attribute type="xs:string" name="seo-alias" use="optional"/>
<xs:attribute type="xs:string" name="requires-subscription" use="optional"/>
<xs:attribute type="xs:int" name="rating" use="optional"/>
<xs:attribute type="xs:short" name="rates" use="optional"/>
<xs:attribute type="xs:short" name="ratesum" use="optional"/>
<xs:attribute type="xs:string" name="duration" use="optional"/>
<xs:attribute type="xs:string" name="season-name" use="optional"/>
<xs:attribute type="xs:int" name="season-number" use="optional"/>
<xs:attribute type="xs:string" name="set-name" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
如何更改它以便它将验证<item>
中的子元素何时以任何顺序出现?
您不能在XSD 1.0中使用xs:all
,因为虽然它允许任何顺序的元素,但它只允许每个元素中的一个或零。
但是你提供的模式不需要任何子元素,这意味着像这样的item
:
<item></item>
仍然有效(因为所有属性也被声明为optional
)。是这样的吗?
如果是这样,你不需要<xs:all>
并且可以替换<xs:sequence>
声明中的<xs:element name="item">
为可选和无界的<xs:choice>
:
<xs:element name="item" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
...
</xs:choice>
<xs:attribute type="xs:short" name="id" use="optional"/>
...
</xs:complexType>
</xs:element>
这将验证空的<item>
元素,包含任何顺序的子元素的<item>
元素,任何数量(包括零)。它将验证这一点:
<item>
<tag id="752" title="пираты"/>
<tag id="894" title="любовь"/>
<category id="71" title="Фильмы"/>
<tag id="1164" title="флот"/>
<country id="515" title="США"/>
<tag id="1789" title="море"/>
<director id="27449" title="Гор Вербински"/>
<tag id="1790" title="сокровища"/>
<tag id="1811" title="нечисть"/>
<genre id="702" title="приключения"/>
<tag id="2292" title="похищение"/>
<year id="227" title="2003"/>
<genre id="674" title="художественное"/>
<genre id="690" title="боевик"/>
<tariffs>
<tariff id="2" type-id="1" type-alias="subscription" price="179" duration="30"/>
<tariff id="6" type-id="2" type-alias="purchase" price="79" duration="30"/>
</tariffs>
<genre id="5938" title="фэнтези"/>
</item>
还有这个:
<item>
<tag id="1789" title="море"/>
<director id="27449" title="Гор Вербински"/>
<tag id="1790" title="сокровища"/>
<tag id="1811" title="нечисть"/>
</item>
然而,这可能不是最好的设计。你真的想让空<item>
s或<item>
s只包含标签和导演吗?如果没有,您可以考虑使用替代设计或使用XSD 1.1。
另一种设计
如果您正在设计此架构,则更好的解决方案是更改设计并在包装器元素中容纳重复元素。这是一个更好的设计,因为它将元素表示为一个组或数组,这实际上就是它们。它使处理它们更容易,在语言映射软件中使用它们等。
如果你可以改变设计,另一种设计可能是一个允许这样的东西的模式:
<item id="17314" ... >
<tariffs>
<tariff .../>
<tariff .../>
</tariffs>
<categories>
<category id="71" title="Фильмы"/>
<category id="72" title="театрь"/>
</categories>
<directors>
<director id="16910" title="Константин Станиславский"/>
<director id="16911" title="Вуди Аллен"/>
<director id="16912" title="Педро Альмодовар"/>
</directors>
<tags>
<tag id="752" title="деньги"/>
<tag id="894" title="любовь"/>
<tag id="1164" title="вещь"/>
</tags>
<countries>
<country id="2543" title="Франция"/>
<country id="2600" title="Испания"/>
<country id="8789" title="Россия"/>
</countries>
<year id="227" title="2003"/>
<genres>
<genre id="674" title="художественное"/>
<genre id="690" title="боевик"/>
<genre id="702" title="приключения"/>
<genre id="5938" title="фэнтези"/>
<genre id="6467" title="фестивальное"/>
<genre id="8964" title="HD фильмы"/>
</genres>
</item>
你可以使用xs:all
来允许每个集合在<item>
中以任何顺序出现一次(允许可选集合,例如tariff
):
<xs:element name="item">
<xs:complexType>
<xs:all>
<xs:element ref="tariffs" minOccurs="0"/>
<xs:element ref="categories"/>
<xs:element ref="directors"/>
<xs:element ref="tags"/>
<xs:element ref="countries"/>
<xs:element ref="year"/>
<xs:element ref="genres"/>
</xs:all>
<xs:attribute type="xs:short" name="id" use="optional"/>
...
</xs:complexType>
</xs:element>
XSD 1.1
你不能在XSD 1.0中使用无界元素的xs:all
。正如我在本答案开头所示,您的解决方案不需要它,因为<item>
中的所有元素都是可选的。但是,如果您确实需要<item>
中的元素,无法更改您的设计并且仍然希望以任何顺序允许元素,则可以使用您提供的相同模式验证代码,只要您将其与XSD 1.1一起使用即可。
为此,您需要使用支持XSD 1.1的解析器并向<xs:schema>
根元素添加两个属性,如下所示:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1">
...
然后你可以在你的XSD中为<xs:sequence>
替换<item>
元素声明中的<xs:all>
,它将在支持XSD 1.1的解析器中验证时有效。