2013-02-15 60 views
5

我想爲書籍設計一個XML模式,需要爲每個書目條目指定一個唯一的ID。但它似乎並不奏效。下面是XSD我使用,XML模式仍然允許重複的ID與唯一

<?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> 

它驗證罰款,即使它不應該(我用相同的ID 2項)。我對XML很感興趣,希望有人能指出我在這裏做錯了什麼?

回答

10

你得放錯了地方的<xs:unique> - 它需要在其中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的選擇器。

3

您是否特別需要使用數字作爲ID值?如果不是這樣,一個可能性是使用xs:ID作爲id屬性類型,而不是xs:string

<xs:attribute name="id" type="xs:ID" use="required"/> 

這樣只有unique XML identifiers被允許作爲id屬性的值。例如,有效的XML標識符不能以數字開頭,因此您必須將您的ID類型更改爲id-1之類的內容。