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.