XML模式仍然允许重复的id具有唯一性

sou*_*rar 6 xml xsd

我正在尝试为书籍设计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>
Run Code Online (Sandbox Code Playgroud)

我试图用这个验证的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>
Run Code Online (Sandbox Code Playgroud)

即使它不应该验证罚款(我已经为2个条目使用了相同的id).我是XML的新手,如果有人能指出我在这里做错了什么,我会很感激吗?

Ian*_*rts 11

你有<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>
Run Code Online (Sandbox Code Playgroud)

如果您希望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>
Run Code Online (Sandbox Code Playgroud)

为了将来参考,请注意,如果您的模式有一个targetNamespace那么那些选择器将无法正常工作,因为选择器XPath中的无前缀名称始终意味着"无命名空间".您需要添加xmlns:tns="<target namespace URI>"到您的xs:schema元素,然后使用选择器tns:Shelf/tns:Book.