Tuesday 26 June 2007

Good use of xsl:key

This is a perfect example of how xsl:key can not only optimize the syntax of your xsl, but also its performance significantly.
In the following XML there are three separate nodesets, children of the same parent, that reference each other via different ids. The purpose of this exercise is to get a list of incidents for each car.

XML


<?xml version="1.0" encoding="UTF-8"?>
<root>
<car>
<CarInfo vin="4FL200212345">
<Owner>J. P. Morgan</Owner>
</CarInfo>
</car>
<car>
<CarInfo vin="3CL200212345">
<Owner>J.P. Thompson</Owner>
</CarInfo>
</car>
<carSpecifics vin="4FL200212345">
<CarMake xrefId="XREF12345">
<Color>Red</Color>
<Style>Sedan</Style>
</CarMake>
</carSpecifics>
<carSpecifics vin="3CL200212345">
<CarMake xrefId="XREF67890">
<Color>Red</Color>
<Style>Sedan</Style>
</CarMake>
</carSpecifics>
<CarXref xrefId="XREF12345">
<Incident>Friday Crash</Incident>
</CarXref>
<CarXref xrefId="XREF67890">
<Incident>Sat Crash</Incident>
</CarXref>
</root>


XSL

<xsl:key name="incidents"
match="/root//CarXref/Incident" use="../@xrefId"/>
<xsl:key name="carSpecifics"
match="/root/carSpecifics/CarMake/@xrefId" use="../../@vin"/>

<xsl:template match="/">
<incidents>
<xsl:apply-templates select="root/car/CarInfo/@vin"/>
</incidents>
</xsl:template>

<xsl:template match="@vin">
<xsl:apply-templates select="key('carSpecifics',.)"/>
</xsl:template>

<xsl:template match="@xrefId">
<xsl:apply-templates select="key('incidents', .)"/>
</xsl:template>

<xsl:template match="Incident">
<incident>
<xsl:value-of select="."/>
</incident>
</xsl:template>

2 comments:

Antony said...

Hi Miguel,

Should:

<xsl:key name="incidents"
match="/root//CarXref/Incident" use="../@xrefId"/>

...not be:

<xsl:key name="incidents"
match="/root/CarXref/Incident" use="../@xrefId"/>

?

Although not particularly true in this instance, surely the use of // would be more inefficient and is unnecessary in this case?

Antony

Miguel de Melo said...

Hi Antony,

Good point, in this case it's unnecessary to use the double backslash. I am not sure if that was a typo, or a way to show how the xsl:key can index more complex xpath.

Double back slashes have a prety bad reputation but I believe if they're used with care, in the right environment and file size, they can be really usefull.

Thanks for the comment,
Miguel