[xsl] A problem using the xsl:key facility

Subject: [xsl] A problem using the xsl:key facility
From: Nathan Potter <ndp@xxxxxxxxxxxxxxxxxxxx>
Date: Tue, 20 Jul 2010 16:17:37 -0400
Greetings,

I am struggling with the use of an xsl:key in a particular construct. I can't seem to get the xsl:key to work from within an xsl:for-each loop. The key is defined outside of any template, and the for-each is within a template. The key works fine outside of the for-each. Do I misunderstand something fundamental about the scope of a key?



I please see below for the XSLT, and the input and output files.

I am using Oxygen and Saxon-B 9.1.0.7


Thanks in advance!



Sincerely,


Nathan



######################
XSL Transform:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
     xmlns:xs="http://www.w3.org/2001/XMLSchema";
     exclude-result-prefixes="xs"
     version="2.0">

<xsl:output method='xml' encoding='UTF-8' indent='yes'/>

<xsl:key name="service-by-name" match="//service" use="@name"/>


<xsl:template match="catalog"> <catalog> <xsl:apply-templates/> </catalog> </xsl:template>

   <xsl:template match="service" />
   <xsl:template match="serviceName" />
   <xsl:template match="text()" />



<xsl:template match="dataset">

<!-- Gather the serviceName's -->
<xsl:variable name="serviceNames" >
<xsl:if test="@serviceName">
<xsl:element name="serviceName"><xsl:value-of select="@serviceName"/></xsl:element>
</xsl:if>
<xsl:copy-of select="serviceName | metadata/serviceName"/>
</xsl:variable>




       <xsl:choose>
           <xsl:when test="boolean(dataset)">
               <xsl:element name="NestedDataset">
                   <xsl:attribute name="name">
                       <xsl:value-of select="@name"/>
                   </xsl:attribute>
                   <xsl:apply-templates/>
               </xsl:element>

           </xsl:when>
           <xsl:otherwise>
               <xsl:element name="dataset">
                   <xsl:attribute name="name">
                       <xsl:value-of select="@name"/>
                   </xsl:attribute>

                   <xsl:element name="myServiceNames">
                       <xsl:copy-of select="$serviceNames"/>
                   </xsl:element>



<TheForEachLoopOutputIsInHere>
<xsl:for-each select="$serviceNames/serviceName" >
<xsl:variable name="sName"><xsl:value-of select="."/></xsl:variable>


<xsl:comment>
Sanity Check #1: Copy the current node.
</xsl:comment>
<xsl:element name="copy- of_current_serviceName_element"><xsl:copy-of select="."/></xsl:element>


<xsl:comment>
Sanity Check #2: Enshrine the string value of the variable sName in a new element.
</xsl:comment>
<xsl:element name="value- of_sName_variable"><xsl:value-of select="$sName"/></xsl:element>


<xsl:comment>
Sanity Check #3: Use the key "service-by- name" to retrieve the
service element identified by the sName variable. This always fails
within the xsl:for-each loop.
</xsl:comment>
<xsl:element name="copy-of_service_element">
<xsl:attribute name="name"><xsl:value-of select="$sName"/></xsl:attribute>
<xsl:copy-of select="key('service-by-name', $sName)"/>
</xsl:element>
<!-- <xsl:element name="aservice"><xsl:copy-of select="."/></xsl:element> -->
</xsl:for-each>
</TheForEachLoopOutputIsInHere>
<xsl:comment>
Sanity Check #4: Outside of the xsl:for-each loop we can get things from the key "service-by-name".
Here I'll just get a copy of the service called "wcs".
</xsl:comment>
<xsl:copy-of select="key('service-by-name','wcs')"/>


</xsl:element>


</xsl:otherwise> </xsl:choose>

</xsl:template>




</xsl:stylesheet>












######################
XML Input:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>

   <service name="woo" serviceType="OPENDAP" base="/opendap/hyrax1/" />
   <service name="hoo" serviceType="OPENDAP" base="/opendap/hyrax2/" />
   <service name="boo" serviceType="OPENDAP" base="/opendap/hyrax3/" />

<service name="all" serviceType="Compound" base="">
<service name="ncdods" serviceType="OPENDAP" base="/thredds/ dodsC/" />
<service name="wcs" serviceType="WCS" base="/thredds/wcs/" />
<service name="wms" serviceType="WMS" base="/thredds/wms/" />
</service>



<dataset name="Dataset 0">
<dataset name="dataset1" serviceName="wcs" urlPath="satellite/ PH/ssta/1day">
<serviceName>all</serviceName>
</dataset>
</dataset>



</catalog>







######################
XML Output:
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<NestedDataset name="Dataset 0">
<dataset name="dataset1">
<myServiceNames>
<serviceName>wcs</serviceName>
<serviceName>all</serviceName>
</myServiceNames>
<TheForEachLoopOutputIsInHere><!--
Sanity Check #1: Copy the current node.
--><copy-of_current_serviceName_element>
<serviceName>wcs</serviceName>
</copy-of_current_serviceName_element>
<!--
Sanity Check #2: Enshrine the string value of the variable sName in a new element.
--><value-of_sName_variable>wcs</value- of_sName_variable>
<!--
Sanity Check #3: Use the key "service-by- name" to retrieve the
service element identified by the sName variable. This always fails
within the xsl:for-each loop.
--><copy-of_service_element name="wcs"/>
<!--
Sanity Check #1: Copy the current node.
--><copy-of_current_serviceName_element>
<serviceName>all</serviceName>
</copy-of_current_serviceName_element>
<!--
Sanity Check #2: Enshrine the string value of the variable sName in a new element.
--><value-of_sName_variable>all</value- of_sName_variable>
<!--
Sanity Check #3: Use the key "service-by- name" to retrieve the
service element identified by the sName variable. This always fails
within the xsl:for-each loop.
--><copy-of_service_element name="all"/>
</TheForEachLoopOutputIsInHere>
<!--
Sanity Check #4: Outside of the xsl:for-each loop we can get things from the key "service-by-name".
Here I'll just get a copy of the service called "wcs".
--><service name="wcs" serviceType="WCS" base="/ thredds/wcs/"/>
</dataset>
</NestedDataset>
</catalog>





============================================================ Nathan Potter Oregon State University, COAS ndp at coas.oregonstate.edu 104 Ocean. Admin. Bldg. 541 231 3317 voice Corvallis, OR 97331-5503 541 737 2064 fax

Current Thread