I have an xsl:variable
that contains a list of nodes. When I try to loop over them with for-each, I get no results. I'm using saxon655 and java 1.8.0_181.
Here is the xslt:
<?xml version="1.0"?>
<xsl:stylesheet xmlns="http://www.w3.org/1999/xhtml"
xmlns:exsl="http://exslt.org/common"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:variable name="products">
<array>
<item><name>Scooby</name><value>Doo</value></item>
<item><name>snack</name><value>cookies</value></item>
</array>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="exsl:node-set($products)">
<xsl:message>LOOP</xsl:message>
<xsl:value-of select=".//name" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The xml:
<?xml version='1.0' encoding='UTF-8'?>
<book>
text
</book>
Finally, my command:
/usr/bin/java -cp /usr/local/share/saxon/saxon.jar com.icl.saxon.StyleSheet test.xml test_run.xsl
When I run the command I receive one line of output LOOP
.
I expected to get the message and the value for name
once for each item in the variable array.
Doing exsl:node-set($products)
returns a single document node, which contains the rest of the XML in your variable, so what you need to do is this...
<xsl:for-each select="exsl:node-set($products)/array/item">
However, this won't work immediately, because you defined a default namespace declaration in your XSLT (xmlns="http://www.w3.org/1999/xhtml"
). This means the elements within the variable, being un-prefixed, will be in that namespace.
So, unless you have a reason to have array
and item
in a namespace, declare the variable like so
<xsl:variable name="products" xmlns="">
Try this XSLT
<xsl:stylesheet xmlns="http://www.w3.org/1999/xhtml"
xmlns:exsl="http://exslt.org/common"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:variable name="products" xmlns="">
<array>
<item><name>Scooby</name><value>Doo</value></item>
<item><name>snack</name><value>cookies</value></item>
</array>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="exsl:node-set($products)/array/item">
<xsl:value-of select="name" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Alternatively, if you need want array
and item
in the namespace though, you could handle them like so:
<xsl:stylesheet xmlns="http://www.w3.org/1999/xhtml"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:exsl="http://exslt.org/common"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:variable name="products">
<array>
<item><name>Scooby</name><value>Doo</value></item>
<item><name>snack</name><value>cookies</value></item>
</array>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="exsl:node-set($products)/xhtml:array/xhtml:item">
<xsl:value-of select="xhtml:name" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>