XML schema still allowing duplicate id's with unique
xml, xsd
Solution
You've got the `<xs:unique>` in the wrong place - it needs to be inside the definition of the ancestor element within which the `Book` elements should be unique, not in the `Book` element definition itself. The following would force Book ids to be unique within each shelf, but would allow the same ID on different shelves:
<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>
If instead you want the IDs to be globally unique across all shelves then put the unique constraint at the `BookShelf` level and adjust the selector appropriately:
<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>
For future reference, note that if your schema had a `targetNamespace` then those selectors would not work as-is, because unprefixed names in selector XPaths always mean "no namespace". You would need to add `xmlns:tns="<target namespace URI>"` to your `xs:schema` element and then use a selector of `tns:Shelf/tns:Book`.
Problem
I am trying to design an XML schema for books where a unique ID needs to be specified for each book entry. However it just doesn't seem to work. Below is the XSD i am using, ``` <?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> ``` The XML I am trying to validate with this is, ``` <?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> ``` which is validating fine even though it should not (I've used the same id for 2 entries). I'm pretty new at XML and would appreciate if someone could please point out what I am doing wrong here?