XML and uniqueness: xs:id, xs:unique and xs:key

A few years ago at my workplace we came up with an xml format for rendering forms – this was in the days when XAML was being discussed but had not yet RTM’ed.

The xml documents are made up of Forms, containing Pages, containing Groups, containing Sections, containing Controls. The Control elements have an id attribute which I needed to be unique throughout the document.

At the time I chose to use xs:ID as the type for the attribute in the schema, and all was good.

<Control id="my Control1" />


Until now... In my latest project we’re generating these XML for definitions and I have decided to use GUIDs for the id’s. Obviously GUIDS meet my needs for uniqueness, however, xs:ID requires that its values begin with letters not numbers. This is not acceptable:

<Control id="5ae88e52-f12f-4aaa-a56f-b00cd9d7cc95" />


So, I had to find something else – enter xs:unique and xs:key. These types are less straight forward. They both require child elements: xs:selector – which locates the part of the document where the constraint applies – and xs:field which states the unique field. For example:

<xs:key name="uniqueControlId">
<xs:selector xpath="ns1:Pages/ns1:Page/ns1:Group/ns1:Section/ns1:Controls/ns1:Control"/>
<xs:field xpath="@id"/>
</xs:key>


Another crucial factor is where the type is placed – as that defines the scope of the uniqueness. So, by placing this definition on my root element it means that the Control’s id must be unique throughout the document.

Something else to watch out for is that in using xpath to locate the appropriate elements you need to qualify it with a namespace prefix (if you’re using namespaces, that is). Even though my schema had a target namespace specified I still had to add it again with a prefix in order to correctly write the xpath. E.g.:

<xs:schema xmlns:ns1="http://companyname/schemas/2009" targetNamespace="http://companyname/schemas/2009" ... />


Lastly, then what is the difference between xs:key and xs:unique? Well, you define them in the same way – except that xs:key requires that the stated field must exist, whereas xs:unique does not.

Hopefully, all that makes sense and the Gods of XML are appeased!

Comments