我正在尝试为书籍设计XML架构,其中需要为每个书籍条目指定唯一ID。然而它似乎没有用。以下是我正在使用的XSD,
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="BookShelf">
<xs:complexType>
<xs:sequence>
<xs:element name="Description" type="xs:string" minOccurs="0"/>
<xs:element name="Shelf" type="ShelfType" minOccurs="1" maxOccurs="10"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="ShelfType">
<xs:sequence>
<xs:element ref="Book" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Book">
<xs:complexType>
<xs:sequence>
<xs:element name="Title" type="xs:token"/>
<xs:element name="Language" type="xs:language"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required"/>
</xs:complexType>
<xs:unique name="unique-bookId">
<xs:selector xpath="Book"/>
<xs:field xpath="@id"/>
</xs:unique>
</xs:element>
</xs:schema>
我试图用此验证的XML是
<?xml version="1.0"?>
<BookShelf>
<Description>My bookshelf</Description>
<Shelf>
<Book id="1">
<Title>Seitsemän veljestä</Title>
<Language>fi</Language>
</Book>
<Book id="1">
<Title>Another title</Title>
<Language>en</Language>
</Book>
</Shelf>
</BookShelf>
即使它不应该验证罚款(我已经为2个条目使用了相同的id)。我是XML的新手,如果有人能指出我在这里做错了什么,我会很高兴吗?
答案 0 :(得分:10)
你有<xs:unique>
在错误的地方 - 它需要在祖先元素的定义内,其中Book
元素应该是唯一的,而不是在Book
元素定义本身。以下将强制Book ID在每个架子中是唯一的,但在不同的架子上允许相同的ID:
<xs:element name="BookShelf">
<xs:complexType>
<xs:sequence>
<xs:element name="Description" type="xs:string" minOccurs="0"/>
<xs:element name="Shelf" type="ShelfType" minOccurs="1" maxOccurs="10">
<xs:unique name="unique-bookId">
<xs:selector xpath="Book"/><!-- selects books on this shelf -->
<xs:field xpath="@id"/>
</xs:unique>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
如果您想让ID在所有货架上全局唯一,那么将唯一约束放在BookShelf
级别并适当调整选择器:
<xs:element name="BookShelf">
<xs:complexType>
<xs:sequence>
<xs:element name="Description" type="xs:string" minOccurs="0"/>
<xs:element name="Shelf" type="ShelfType" minOccurs="1" maxOccurs="10"/>
</xs:sequence>
</xs:complexType>
<xs:unique name="unique-bookId">
<xs:selector xpath="Shelf/Book"/><!-- selects books on all shelves -->
<xs:field xpath="@id"/>
</xs:unique>
</xs:element>
为了将来参考,请注意,如果您的架构有targetNamespace
,那么这些选择器将无法正常工作,因为选择器XPath中的无前缀名称始终意味着“无命名空间”。您需要将xmlns:tns="<target namespace URI>"
添加到xs:schema
元素,然后使用tns:Shelf/tns:Book
的选择器。
答案 1 :(得分:3)
您是否特别需要使用数字作为ID值?如果没有,则有一种可能性是使用xs:ID
作为id
属性类型而不是xs:string
:
<xs:attribute name="id" type="xs:ID" use="required"/>
这样只允许unique XML identifiers作为id
属性的值。但是,有效的XML标识符不能以数字开头,因此您必须将ID类型更改为id-1
之类的内容。