Simple and easy to use within their domain, IDs and IDREFs keep the
limitations of their DTDs ancestors. W3C XML Schema provides a more
flexible feature for defining identity constraints without limitation
on its lexical space and allowing local keys and references, as well
as multinodes keys.
Another important difference is that the ID/IDREF checks are done on
datatypes based on xs:NMTOKEN datatypes, while the
checks that we will see hereafter can be performed on other
datatypes, and the comparisons will be done on the actual value
spaces rather than on their string representations from the lexical
space. These checks are based on a set of XPath
expressions and are defined through three different (but similar)
constructs to test the uniqueness of a value, define a key, and
define a key reference.
9.2.4. Key References
Despite its name, xs:keyref can be used not only to define a
reference to xs:key, but
also to xs:unique.
The usage of xs:keyref is
straightforward and similar to the usage of xs:key or xs:unique, with an important point worth
mentioning: the refer attribute of xs:keyref should refer to a xs:key or xs:unique element defined under the same
element or under one of their ancestors.
TIP:
The reason for this rule is that the
"identity-constraint tables" where
the keys and references are stored are local to an element and its
ancestors.
The definitions of matching xs:unique or xs:key and xs:keyref need to be done within the same
element, or else one of its ancestors has an impact on the choice of
this location. If, for instance, our books and authors are kept in
separate sections of our document:
<library>
<books>
<book>
.../...
<author-ref ref="Charles M. Schulz"/>
.../...
</book>
.../...
</books>
<authors>
<author>
<name>
Charles M. Schulz
</name>
.../...
</author>
.../...
</authors>
</library>
It's good practice to define a modular schema by
locating the constraints as near as possible to the elements they
control. A natural fit is to locate a key in the
authors element and the matching keyref in the
books element. However, since a xs:keyref needs to be in the same element as
the matching xs:key or one
of its ancestors, and books isn't
an ancestor of authors, the xs:keyref definition can only be done in the
library element. (The xs:key can be defined either in the
library or in the authors
element.)
In the previous example, locating the xs:key definition within
library or authors was only a
matter of style, since the authors are unique both within a
library and within the authors
elements. However, W3C XML Schema allows for situations in which this
isn't the case and in which a key is unique within
the scope of a subelement without being unique within the whole
document.
Let's modify the previous example to define several
categories of authors:
<library>
<books>
<book>
.../...
<author-ref ref="Charles M. Schulz"/>
.../...
</book>
.../...
</books>
<authors>
<category id="comics">
<author>
<name>
Charles M. Schulz
</name>
.../...
</author>
.../...
</category>
<category id="novels">
.../...
</category>
.../...
</authors>
</library>
Defining a xs:key (or
xs:unique) within
library or authors specifies a
uniqueness within the scope of the entire library. Defining a list of
authors within category specifies a uniqueness
within this category only, and allows authors with the same name to
be defined under several categories.
It is perfectly valid, per W3C XML Schema, to define a xs:key under category
and a matching xs:keyref under
library (since library is an
ancestor of category). By doing so, a new
constraint is added to authors' names. When an
author is referenced within a book, her name has to be unique within
the scope of the xs:keyref.
Applied to our instance document, this means that if
"Charles M. Schulz" was not
referenced in one of the books, he can be defined in several
categories; since he is referenced in one book, his name must be
defined once only.
TIP:
While this behavior is described in the Recommendation, the results
may be surprising for schema designers. It is probably good practice
to keep the definitions of the xs:key (or xs:unique) and their matching xs:keyref in the same elements.
9.2.5. Permitted XPath Expressions
The W3C XML Schema Recommendation
states that "to reduce the burden on implementers,
in particular implementers of streaming processors, only restricted
subsets of XPath expressions are allowed" in
xs:selector and xs:field. The result of this statement is a
limited subset of XPath that allows only the selection of nodes that
are descendants of or are part of the current locations.
The XPath expressions allowed in xs:selector must exclusively go deeper into the
hierarchy of the XML element nodes, do not allow any tests in the
XPath steps, and must match a set of elements. In addition, the XPath
expressions allowed in xs:field can also select attributes.
The full BNF for this subset is given in the reference guide. Rather
than giving a verbose explanation, let's see some
examples of what is possible and what is not.
The following are allowed:
- xpath="author"
-
Selects the child elements named author that do
not belong to any namespace.
- xpath="author|character"
-
Selects the child elements named author or
character that do not belong to any namespace.
- xpath="lib:author"
-
Selects the child elements named author that
belong to the namespace whose prefix is
"lib".
- xpath="*"
-
Selects all the child elements.
- xpath="lib:*"
-
Selects all the child elements that belong to the namespace whose
prefix is "lib".
- xpath="authors/author"
-
Selects all the authors/author
child elements.
- xpath=".//author"
-
Selects all the elements that are descendants of the current node,
named author, and don't belong to
any namespace.
- xpath="author/@id"
-
Selects the id attribute of the
author child element (allowed only for
xs:field, and not for
xs:selector).
- xpath="@id|@name"
-
Selects @id or @name (valid
only in xs:field, since
attributes are forbidden in xs:selector).
The following are forbidden:
- xpath="/library/author"
-
Absolute paths are not allowed.
- xpath="../author"
-
The parent axis is not allowed.
- xpath=".//*[@id]"
-
Tests are not allowed.
- xpath="author[@type='comics']"
-
Tests are not allowed.
- xpath="substring-after(@xlink:href, `#')"
-
Function calls are not allowed.
- xpath="//author"
-
Absolute paths are not allowed.
TIP:
Default namespaces do not apply within XPath expressions, and
elements and attributes must always be qualified by a prefix if they
belong to a namespace.