An Illustration of the XSLT Key Construct
The information below is an extract from Crane Softwrights
Ltd.'s XSLT/XPath book Practical Transformation Using XSLT
and XPath (ISBN 1-894049-06-3). The current edition can be
obtained through the
http://www.CraneSoftwrights.com/training/ page. See that page
for details regarding the free updates of all editions to customers
of any edition.
Section 8-2: Content and Document Referencing Techniques (Page
242)
The stylesheet can identify key nodes of the source tree for
subsequent fast access by the XSLT processor:
- identifies all source tree nodes for each declared
key for stylesheet manipulation with a simple name
- builds lookup table of member items based on an
equality test for the lookup value
- e.g.: relate all employee records to the employee's
respective manager's employee record matching each employee's
ManagedBy sub-element content value with the
corresponding employee record with the same value for its
emp= attribute
The XSLT processor can optimize searching in the lookup
table
- all values are fixed after the source tree is
processed
- the processor can index the table for quick
retrieval based on lookup value
- faster return of selected nodes than traversing the
axes using XPath expressions and predicates evaluated at the point
of reference
Not all processors support <xsl:key>
Establishing a lookup table of key relationships in a
declarative fashion
When indexing behavior similar to XML
ID/IDREF attribute cross-referencing values is
required by either attribute or element content, the stylesheet
writer can define and reference key values reflecting the implicit
cross-references:
- keys have three aspects of definition in the
<xsl:key> top-level instruction:
- the namespace-qualified name of the key
-
name="name-of-key-table"
- the collection of key nodes distinguished from
other collections of key nodes
- multiple declarations with the same name
cumulatively build the members in the collection of that name
- the nodes that have the key
-
match="identifying-pattern-of-nodes-in-key-table"
- a XPath matching pattern expression
- similar to count= attribute in
<xsl:number/>
- the lookup values of the keyed nodes
-
use="expression-evaluating-the-value-of-key-in-the-set"
- an XPath selection expression
- if relative, then evaluated relative to each keyed
node
- expression evaluated to a string
- string values need not be unique
- nodes with like values are ordered in document
order
- the index built for a key is somewhat dissimilar to
ID/IDREF
- key values in the set need not be unique
- there can be multiple key nodes in a document with
the same node, same key name, but different key values
- there can be multiple key nodes in a document with
the same key name, same key value, but different nodes
- a key's value need not be parsed as an XML name
token
- a node relative to the key node can represent the
key's value
- a key's value can be the result of an arbitrary
expression evaluated with the key node as the current node
- a lookup value need not be present in the
collection
Note that a variable reference cannot be used in either the
match= or use= expressions outside of a
predicate.
Using a key
key(key-name,non-node-set-value-converted-to-string)
- returns that subset of key nodes whose indexed key
value is equal to the given string lookup value
key(key-name,node-set)
- returns the union of the call to key()
with the value of each of the nodes in the node set as a lookup
value
Predicates can be applied to the returned node set
- key('taxes', 'Canada')[1]
- returns only the first node of all nodes in the
'taxes' key table whose lookup value is the string
'Canada'
- like lookup values are returned in document order
of the nodes indexed, thus, this returns the first such node in
document order
- key('taxes',
'Canada')[@type='federal'][1]
- of all nodes returned by the key function, return
only the first whose type= attribute is
'federal'
The following example illustrates how keys can be used to obtain
the value of an employee's name indirectly from the value of an
attribute (though another model might have the value in sub-element
content) used to reference the employee information of a manager:
The following steps correspond to the diagram indicating how the
value "John Smith" is obtained as the name of the manager of "Joe
Green" indirectly through the emp= attribute of the
<ManagedBy> element:
- the template rule for <ManagedBy> needs to
calculate a value from another node based on an attribute value in
emp= (in another model it could just as well be based
on an element node's value rather than an attribute node's
value)
- the target value calculation begins by first referencing the
key named "people", using the first argument to the
key() function, specifying which of the lookup key
tables that were created by the XSLT processor based on values
found in the source tree
- the key named "people" is declared in a top-level
<xsl:key> element building a table of nodes
matching the given node-set expression indicated with
match= (all element nodes named
"Employee")
- the use= attribute specifies the expression whose
evaluated value, relative to each match= node, that is
used for the lookup comparison value in the key table (the value of
the first child element node named "SSN" relative to
the element nodes named "Employee")
- the second argument to key() function indicates
the node (emp= attribute) relative to the current node
(ManagedBy element) whose value is used for the search
comparison with the key values (the attribute node for
emp=)
- the example indicates the string value "1234" is
what is searched for among the key lookup values
- key() returns all key nodes (Employee
elements) whose lookup value is the string equivalent of the
expression value for what is being searched for (only one node in
this example)
- the <xsl:value-of> is calculated by then
evaluating the complete expression by obtaining the XPath
expression (the child element node named "Name")
relative to the returned set of key nodes (Employee
elements), thus returning the resulting value (the string "John
Smith")
Note that the evaluation of key('people','1234') would
have produced the same result since the lookup value is the
supplied string instead of an evaluated expression.
|
CRANE SOFTWRIGHTS LTD.
|