How to use <xsl:key> to perform a simple lookup in XSLT
Performing a simple lookup is a useful XML/XSLT pattern — lets look at matching an element in one XML document with a value/attribute in another XML document
Example — matching element value to attribute value
document.xml
In this XML document we have a simple list of <lookup> elements within a <history> element. The aim will be to use the value of the <lookup> elements to pull in content from a different XML document (index.xml) during an XSLT transformation.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="key-index.xsl"?>
<history>
<lookup>Tiberius</lookup>
<lookup>Caligula</lookup>
<lookup>Nero</lookup>
<lookup>Claudius</lookup>
</history>
index.xml
Here is a simple XML document with a list of <entry> elements with attribute “name” and the value of the attributes match the values of the elements in the document.xml.
<?xml version="1.0" encoding="UTF-8"?>
<index>
<entry name="Tiberius">Tiberius (Tiberius Julius Caesar Augustus) was emperor from AD 14 until 37.</entry>
<entry name="Caligula">Caligula (Gaius Caesar Augustus Germanicas) was emperor from AD 37 until his assassination in AD 41.</entry>
<entry name="Claudius">Claudius (Tiberius Claudius Caesar Augustus) ruled from AD 41 to 54.</entry>
<entry name="Nero">Nero (Claudius Caesar Augustus Germanicas) was the final emperor of the Julio-Claudian dynasty, reigning from AD 54 until AD 68.</entry>
</index>
What we want to achieve in our XSLT transformation is a Lookup from index.xml, given the values in document.xml e.g. — we want to <lookup>Claudius</lookup> in document.xml should pull in the value of <entry name=”Claudius”>…</entry> in index.xml
key-index.xsl
Below is just one way to achieve this lookup using XSLT keys, a matching template on <lookup>, a <xsl:for-each> and <xsl:apply-templates select>.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="lookup" match="entry" use="@name"/>
<xsl:template match="lookup">
<xsl:variable name="name" select="."/>
<xsl:for-each select="document('index.xml')">
<xsl:apply-templates select="key('lookup', $name)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The <xsl:key> sets up a key which matches on <entry> and uses the attribute “name”. Notice that at this point in the document, the stylesheet does not know where the <entry> elements are.
<xsl:key name="lookup" match="entry" use="@name"/>
The key-index.xsl is applied from document.xml so the <xsl:template match=”lookup”> comes into play as the XSLT Processor identifies each <lookup> element.
<xsl:template match="lookup">
<xsl:variable name="name" select="."/>
<xsl:for-each select="document('index.xml')">
<xsl:apply-templates select="key('lookup', $name)"/>
</xsl:for-each>
</xsl:template>
Once the element <lookup> is matched, the value of the element is assigned to the <xsl:variable> variable “name” — this is just make the key() function cleaner.
Next there is a <xsl:for-each> loop which loads the document(‘index.xml’) into the XSLT stylesheet.
There’s a bit of context magic going on here. Note that the XPath function document(“index.xml”) set the context of the following <xsl:apply-templates to index.xml NOT document.xml.
<xsl:for-each select="document('index.xml')">
//the context is index.xml
<xsl:apply-templates select="key('lookup', $name)"/>
</xsl:for-each>
The key function is then looking up within index.xml. Recall that the key was defined as:
<xsl:key name="lookup" match="entry" use="@name"/>
Which is matching the <entry> elements in index.xml.
<?xml version="1.0" encoding="UTF-8"?>
<index>
<entry name="Tiberius">Tiberius (Tiberius Julius Caesar Augustus) was emperor from AD 14 until 37.</entry>
<entry name="Caligula">Caligula (Gaius Caesar Augustus Germanicas) was emperor from AD 37 until his assassination in AD 41.</entry>
<entry name="Claudius">Claudius (Tiberius Claudius Caesar Augustus) ruled from AD 41 to 54.</entry>
<entry name="Nero">Nero (Claudius Caesar Augustus Germanicas) was the final emperor of the Julio-Claudian dynasty, reigning from AD 54 until AD 68.</entry>
</index>
If this didn’t turn your brain in knots and you want to learn more about XSLT, how to use it and understand its place in the Modern Web — follow to learn more.
- Beginners XSLT patterns explained — simple key lookup
- What is XSLT and is it still relevant in a website context in 2024?
- XSLT in the web browser — simple transformations on the server
- Using jQuery with XSLT — .ajax(), .ajax() with Promises, .get()
- XSLT with Fetch() API — modern Javascript with/without Async and Await