We have enumerated the features that key and key references provide beyond those of ID and IDREF: no constraint on datatypes, tests done on values rather than on lexical representation, and independent sets of values for each key. To get a complete picture, we need to see if key and key references can emulate ID and IDREF; in other words, we must determine which features of ID and IDREF are missing from key and key references.
First of all, the location of our key and keyref definition needs to be on the root of the document to fully emulate the ID and IDREF that is global to a document, whatever its document element is. Our best move with W3C XML Schema, which doesn't directly constrain the root node, is to locate our declaration in the global element that is likely to be used as a document element.
Then, to define the xs:selector, we will need to provide the list of all the elements holding ID attributes within a single XPath expression.
The last difference is that ID allows definition of a whitespace-separated list of ID references (through IDREFS datatypes), while there is no similar possibility with xs:key. (There is no xs:keyrefs!)
To use xs:key and xs:keyref, we, therefore, have to modify the instance document that is used in the section about ID and IDREF to transform the list of IDs referencing characters into a series of references, and to use the same convention for IDs and references in all our elements:
<library xsi:noNamespaceSchemaLocation="library-keys-id-key.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <book id="isbn-0836217462"> <isbn> 0836217462 </isbn> <title> Being a Dog Is a Full-Time Job </title> <author-ref ref="au-Charles_M._Schulz"/> <character-ref ref="ch-Peppermint_Patty"/> <character-ref ref="ch-Snoopy"/> <character-ref ref="ch-Schroeder"/> <character-ref ref="ch-Lucy"/> </book> .../... <author id="au-Charles-M.-Schulz"> <name> Charles M. Schulz </name> <nickName> SPARKY </nickName> <born> November 26, 1922 </born> <dead> February 12, 2000 </dead> </author> <character id="ch-Peppermint-Patty"> <name> Peppermint Patty </name> <since> Aug. 22, 1966 </since> <qualification> bold, brash and tomboyish </qualification> </character> ... </library>
The definition follows:
<xs:element name="library"> <xs:complexType> .../... </xs:complexType> <xs:key name="ID"> <xs:selector xpath="book|author|character"/> <xs:field xpath="@id"/> </xs:key> <xs:keyref name="IDREF" refer="ID"> <xs:selector xpath="book/author-ref|book/character-ref"/> <xs:field xpath="@ref"/> </xs:keyref> </xs:element>
This example illustrates the main difference between the two mechanisms: ID/IDREF declarations are done at the level where they are used, and are, therefore, fully integrated with the pseudo-object-oriented features of W3C XML Schema, while key/keyref definitions are done at the level of a common ancestor and rely on the actual structure of the instance documents rather than on its object-oriented schema.
TIP: Since key/keyref rely on the actual structure of the instance documents, they ignore features such as substitution groups. Their XPath expressions need to explicitly define each of the possible element names (except when they use a "*" to indicate "any element" at a particular level).
Copyright © 2002 O'Reilly & Associates. All rights reserved.