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
Do you specifically need to use digits as ID values? If not, one possibility is using xs:ID
as the id
attribute type instead of xs:string
:
<xs:attribute name="id" type="xs:ID" use="required"/>
That way only unique XML identifiers are allowed as values of the id
attribute. A valid XML identifier can't start with a digit, however, so you'll have to change your ID type to something like id-1
, for example.
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
.