Reputation: 9697
I'm trying out a sample of look-up tables in XSLT and am not able to get it to work
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" />
<xsl:key name="classification-lookup" match="classification" use="id" />
<xsl:variable name="classification-top" select="document('')/*/classifications" />
<xsl:template match="BusinessListing">
<listing>
<id>
<xsl:value-of select="id" />
</id>
<xsl:apply-templates select="$classification-top">
<xsl:with-param name="curr-label" select="." />
</xsl:apply-templates>
</listing>
</xsl:template>
<xsl:template match="classifications">
<xsl:param name="curr-label" />
<category>
<xsl:value-of select="key('classification-lookup', $curr-label/listingData/classifications/classificationId)/description" />
</category>
</xsl:template>
<classifications>
<classification>
<id>7981</id>
<description>Category1</description>
</classification>
<classification>
<id>7982</id>
<description>Category2</description>
</classification>
<classification>
<id>7983</id>
<description>Category3</description>
</classification>
<classification>
<id>7984</id>
<description>Category4</description>
</classification>
</classifications>
</xsl:stylesheet>
and the source is as below .
<?xml version="1.0"?>
<BusinessListings>
<BusinessListing>
<id>1593469</id>
<listingData>
<classifications>
<classificationId>7982</classificationId>
<classificationId>7983</classificationId>
</classifications>
</listingData>
</BusinessListing>
</BusinessListings>
In the result below , The category is empty but I need the Classification Id from the source to be matched with the id in the classification tag and the category generated .
<?xml version="1.0" encoding="UTF-8"?>
<listing>
<id>1593469</id> -- Empty I need the Category2 and Category3 here
<category/>
</listing>
I know that I may be wide off mark but I've just started off with XSLT and referred the sample here http://www.ibm.com/developerworks/xml/library/x-xsltip.html . Thanks for the help .
Upvotes: 4
Views: 3673
Reputation: 243449
Your XSLT stylesheet contains an error -- according to spec, any child-element of xsl:stylesheet
(aka top-level element) must be in a non-null namespace:
"*In addition, the xsl:stylesheet element may contain any element not from the XSLT namespace, provided that the expanded-name of the element has a non-null namespace URI. "
If the XSLT processor you are using doesn't raise an error, then it is non-compliant and buggy and shouldn't be used. Find and use a compliant XSLT processor (I am using .NET XslCompiledTransform, Saxon 6.5.5, ..., etc).
There are other errors, too.
Solution:
Define a new namespace with prefix (say) "x:":
Change the embedded <classifications>
to <x:classifications>
-- now this conforms to the Spec.
Perform more changes to the code until you get this transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="my:x" exclude-result-prefixes="x">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="classification-lookup" match="classification"
use="id" />
<xsl:template match="BusinessListing">
<listing>
<id>
<xsl:value-of select="id" />
</id>
<xsl:apply-templates/>
</listing>
</xsl:template>
<xsl:template match="classificationId">
<xsl:variable name="vCur" select="."/>
<xsl:for-each select="document('')">
<category>
<xsl:value-of select=
"key('classification-lookup',$vCur)/description" />
</category>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()"/>
<x:classifications>
<classification>
<id>7981</id>
<description>Category1</description>
</classification>
<classification>
<id>7982</id>
<description>Category2</description>
</classification>
<classification>
<id>7983</id>
<description>Category3</description>
</classification>
<classification>
<id>7984</id>
<description>Category4</description>
</classification>
</x:classifications>
</xsl:stylesheet>
.4. In the above code notice the line: <xsl:for-each select="document('')">
.
The purpose of this is to make the stylesheet the current document. The key()
function operates only on the current document and if you want the embedded classification
elements to be indexed and used, you must change the current document (usually in this way). In XSLT 2.0 the key()
function allows a 3rd argument which is a node from the document whose index should be used.
When this transformation is applied to the provided XML document:
<BusinessListings>
<BusinessListing>
<id>1593469</id>
<listingData>
<classifications>
<classificationId>7982</classificationId>
<classificationId>7983</classificationId>
</classifications>
</listingData>
</BusinessListing>
</BusinessListings>
the wanted, correct result is produced:
<listing>
<id>1593469</id>
<category>Category2</category>
<category>Category3</category>
</listing>
Upvotes: 4