XSL reference documentation generated from the W3C Recommendation 16 November 1999


XSL element key

Keys

Keys provide a way to work with documents that contain an implicit cross-reference structure. The ID, IDREF and IDREFS attribute types in XML provide a mechanism to allow XML documents to make their cross-reference explicit. XSLT supports this through the XPath id function. However, this mechanism has a number of limitations:

Because of these limitations XML documents sometimes contain a cross-reference structure that is not explicitly declared by ID/IDREF/IDREFS attributes.

A key is a triple containing:

  1. the node which has the key

  2. the name of the key (an expanded-name)

  3. the value of the key (a string)

A stylesheet declares a set of keys for each document using the xsl:key element. When this set of keys contains a member with node x, name y and value z, we say that node x has a key with name y and value z.

Thus, a key is a kind of generalized ID, which is not subject to the same limitations as an XML ID:

<key>
  name = qname
  match = pattern
  use = expression
Model: EMPTY
</key>

The xsl:key element is used to declare keys. The name attribute specifies the name of the key. The value of the name attribute is a QName, which is expanded as described in qname. The match attribute is a Pattern; an xsl:key element gives information about the keys of any node that matches the pattern specified in the match attribute. The use attribute is an expression specifying the values of the key; the expression is evaluated once for each node that matches the pattern. If the result is a node-set, then for each node in the node-set, the node that matches the pattern has a key of the specified name whose value is the string-value of the node in the node-set; otherwise, the result is converted to a string, and the node that matches the pattern has a key of the specified name with value equal to that string. Thus, a node x has a key with name y and value z if and only if there is an xsl:key element such that:

Note also that there may be more than one xsl:key element that matches a given node; all of the matching xsl:key elements are used, even if they do not have the same import precedence.

It is an error for the value of either the use attribute or the match attribute to contain a VariableReference.

The key function does for keys what the id function does for IDs. The first argument specifies the name of the key. The value of the argument must be a QName, which is expanded as described in qname. When the second argument to the key function is of type node-set, then the result is the union of the result of applying the key function to the string value of each of the nodes in the argument node-set. When the second argument to key is of any other type, the argument is converted to a string as if by a call to the string function; it returns a node-set containing the nodes in the same document as the context node that have a value for the named key equal to this string.

For example, given a declaration

<xsl:key name="idkey" match="div" use="@id"/>

an expression key("idkey",@ref) will return the same node-set as id(@ref), assuming that the only ID attribute declared in the XML source document is:

<!ATTLIST div id ID #IMPLIED>

and that the ref attribute of the current node contains no whitespace.

Suppose a document describing a function library uses a prototype element to define functions

<prototype name="key" return-type="node-set">
<arg type="string"/>
<arg type="object"/>
</prototype>

and a function element to refer to function names

<function>key</function>

Then the stylesheet could generate hyperlinks between the references and definitions as follows:

<xsl:key name="func" match="prototype" use="@name"/>

<xsl:template match="function">
<b>
  <a href="#{generate-id(key('func',.))}">
    <xsl:apply-templates/>
  </a>
</b>
</xsl:template>

<xsl:template match="prototype">
<p><a name="{generate-id()}">
<b>Function: </b>
...
</a></p>
</xsl:template>

The key can be used to retrieve a key from a document other than the document containing the context node. For example, suppose a document contains bibliographic references in the form <bibref>XSLT</bibref>, and there is a separate XML document bib.xml containing a bibliographic database with entries in the form:

<entry name="XSLT">...</entry>

Then the stylesheet could use the following to transform the bibref elements:

<xsl:key name="bib" match="entry" use="@name"/>

<xsl:template match="bibref">
  <xsl:variable name="name" select="."/>
  <xsl:for-each select="document('bib.xml')">
    <xsl:apply-templates select="key('bib',$name)"/>
  </xsl:for-each>
</xsl:template>