XSLT, parameters, for-each and variables

Published October 20th, 2006

Here’s another one of those really obscure things that will probably not be important to anyone at all, ever. Anyway, it took me a while to work it out so I’m going to record it here for future reference.

The problem: using XSLT, I wanted to pass a node-tree as a parameter to a template and then loop over it using xsl:for-each. Now I can already sense XSLT purists’ hackles rising: yes I should probably have tried harder to come up with some way of achieving the same thing using template matching. But please take pity on my poor brain! It really hasn’t managed to absorb all the subtleties of XSLT yet (even after two years battling with it) and as hard as I tried, I just couldn’t achieve what I needed to in a pure functional way. I know, I know: I’m going to hell.

Anyway, first off I worked out that to pass a node-tree as a parameter you have to use xsl:copy-of rather than xsl:value-of (which just flattens the node-tree into a string). But then, just as I was celebrating getting over that particular hurdle, I found that trying to use a variable in a for-each statement like this (simplified for readability):

<xsl:template>
	<xsl:with-param name="data"/>
	<xsl:for-each select="$data/*">
		
	</xsl:for-each>
</xsl:template>

…gave an ‘Invalid Type’ error.

The key (at least as far as libxslt, the XSLT parser library used by PHP5, is concerned), is something called EXSLT. As the acronym suggests, EXSLT provides extensions to XSLT. One of these is a function called node-set(), which “returns a node-set from a result tree fragment”. Bingo!

To get EXSLT to work, first you need to add it to your stylesheet declaration:

xmlns:exslt="http://exslt.org/common"

Then just call the function (remembering to include the exslt: namespace):

<xsl:template>
	<xsl:with-param name="data"/>
	<xsl:for-each select="exslt:node-set($data)/*">
		
	</xsl:for-each>
</xsl:template>

NB: if you’re using PHP5, you’ll need to ensure that EXSLT is enabled on your PHP installation. To do this, you can check the result of the XSLTProcessor->hasExsltSupport() method.

Get a Trackback link

1 Comments

  1. edward on April 26, 2007

    I’m surprised there is no way to do this without referring to an external namespace. I have been trying to figure out exactly this for hours, and could come up with nothing. I was trying to work with it as a variable, since it seems that the parameter $data behaves exactly like a local variable $data. but no luck… I found the syntax to do a for-each loop with a global variable, but I never found a way to do it with a local variable.

    thanks though, this works, and is exactly what I need.

Leave a comment

Comment Policy: First time comments are moderated. Please be patient.

OpenID

Anonymous