key
To quote from the W3C standard: "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."
Syntax
<key> ::= "key" <quote> <name> <quote>
"using" <quote> <xpath expression> <quote>
"keyNodes" <quote> <xpath expression> <quote>
Options
name
|
The name of this key. |
using
|
The XPath expression defining the nodes to use. |
keyNodes
|
The XPath expression defininng which key to use. |
Elements
None.
Examples
Consider a simple list of composers:
<composers>
<composer>
<firstnames>Johann Sebastian</firstnames>
<lastname>Bach</lastname>
</composer>
<composer>
<firstnames>Leopold</firstnames>
<lastname>Mozart</lastname>
</composer>
<composer>
<firstnames>Carl Philipp Emanuel</firstnames>
<lastname>Bach</lastname>
</composer>
<composer>
<firstnames>Johann Christian</firstnames>
<lastname>Bach</lastname>
</composer>
<composer>
<firstnames>Wolfgang Amadeus</firstnames>
<lastname>Mozart</lastname>
</composer>
</composers>
Say we wished to extract all the members of a single family and list them in a table. Using a key construction we can use the following
Rexsel script which searches all <composer> tags and returns a list of nodes match 'lastname'.
stylesheet {
version "1.0"
xmlns "xml" "http://www.w3.org/XML/1998/namespace"
key "surname-search" using "composer" keyNodes "lastname"
match using "/" {
element "html" {
element "body" {
element "h2" { text "Composers" }
element "table" {
element "tr" {
element "th" { text "First Names" }
element "th" { text "Last Name" }
element "th" { text "Marks" }
}
foreach "key('surname-search', 'Bach')" {
element "tr" {
element "td" { value "firstnames" }
element "td" { value "lastname" }
}
}
}
}
}
}
}
The 'foreach' XPath expression "key('surname-search', 'Bach')" uses the list of
nodes produced by the key that matches against 'lastname', in this case the string "Bach". This will produce the
XML
<html>
<body>
<h2>Composers</h2>
<table>
<tr>
<th>First Names</th>
<th>Last Name</th>
<th>Marks</th>
</tr>
<tr>
<td>Johann Sebastian</td>
<td>Bach</td>
</tr>
<tr>
<td>Carl Philipp Emanuel</td>
<td>Bach</td>
</tr>
<tr>
<td>Johann Christian</td>
<td>Bach</td>
</tr>
</table>
</body>
</html>
Not using the key statement would require the loop XPath to be replaced with
foreach "//composer/lastname[. = 'Bach']/parent::*" {
element "tr" {
element "td" { value "firstnames" }
element "td" { value "lastname" }
}
}
which is slightly more complex.
Errors
Leaving out the name.
key using "composer" keyNodes "surname"
gives
**** (115) Expected name after "key" in line 5
Insert name.
Similarly forgetting either of the expressions.
key "surname-search" using keyNodes "surname"
gives
*** (130) Missing expression after "using" in line 5
Insert expression.
**** (148) "key" requires "using" in line 5
Check syntax requirements for "key"
Not having unique key names.
key "surname-search" using "composer" keyNodes "surname"
key "surname-search" using "composer" keyNodes "surname"
gives
*** (110) "surname-search" symbol in 5 already declared in line 6
Remove duplicate or check spelling.
Copyright 2024 Hugh Field-Richards. All Rights Reserved.