Hi Hélder
<snip>
In the next xsl I want to make that the param "cod" be incremented in each
time that the <xsl:for-each> cicle occurs, but it's result is an error:
"javax.xml.transform.TransformerException: xsl:with-param is not allowed in
this position in the stylesheet!"
Why?!
Tks
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:xalan="http://xml.apache.org/xslt">
<xsl:param name="cod">0</xsl:param>
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:for-each select=".//Boy">
<xsl:with-param name="cod" select="number($cod+1)"/>
<!--make other things-->
</xsl:for-each>
</xsl:template>
</xsl:transform>
</snip>
There's a few errors here. Firstly, there's the issue of what you're
actually trying to do. XSL is a functional not a procedural language and
therefore once parameters are set (either globally or locally) they cannot
be altered. These, and variables (known as the variable-binding elements),
are variables in the mathematical sense that they represent any value, not
in the literal sense that they "vary"! You should not think in terms of a
for-each being an iteration. Each matching node is processed independantly
of the others.
Secondly, parameters (and variables) can only be defined at the top level of
the stylesheet (as a child of <xsl:stylesheet>) or as a child of
<xsl:template>. That is, globally to the whole process or locally to the
context of a specific template.
The <xsl:with-param> exists not to reassign an existing parameter, but to
pass a parameter onto another template (overriding any definition of that
parameter within the template) and occurs as a child of <xsl:call-template>.
All of this probably doesn't help you that much, but it leads towards what
you want to acheive. Instead of viewing the <xsl:for-each> as an iteration
with an incrementing parameter, see it as calling another template. If you
then pass this template a parameter which is defined in terms of the number
of preceding Boy elements, you effectively have the increment you are
looking for.
Thus:
<!-- Do not define the parameter globally -->
<xsl:template match="/">
<xsl:for-each select=".//Boy">
<!-- Call the named (not matched) template to handle Boy -->
<xsl:call-template name="doBoy">
<!-- Define the parameter in terms of the number of preceding Boys -->
<xsl:with-param name="cod" select="count(preceding::Boy)+1"/>
<xsl:call-template/>
</xsl:for-each>
</xsl:template>
<!-- Handle Boy -->
<xsl:template name="doBoy">
<!-- Blank parameter which will received the passed value -->
<xsl:param name="cod"/>
<xsl:text>This is Boy number </xsl:text>
<xsl:value-of select="$cod"/>
</xsl:template>
Or in this instance you could also simply define the parameter directly
within doBoy:
<xsl:template match="/">
<xsl:for-each select=".//Boy">
<!-- Call the named (not matched) template to handle Boy -->
<xsl:call-template name="doBoy"/>
</xsl:for-each>
</xsl:template>
<!-- Handle Boy -->
<xsl:template name="doBoy">
<!-- Parameter defined here -->
<xsl:param name="cod" select="count(preceding::Boy)+1"/>
<xsl:text>This is Boy number </xsl:text>
<xsl:value-of select="$cod"/>
</xsl:template>
I think you probably need to read up a bit on XSLTs processing model and the
handling of variable-binding elements. See
http://www.dpawson.co.uk/xsl/sect2/N8090.html and
http://www.dpawson.co.uk/xsl/sect2/N5982.html for starters.
Cheers,
Stuart
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list