Subject: Re: question about position()
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Thu, 17 May 2001 14:51:59 +0100
|
Hi Denis,
> If I have understand correctly, function position() should return
> position in current context, and for-each example is OK, but I don't
> understand why is output from example with apply-templates
> different.
The xsl:apply-templates itself doesn't change the context in which
something is evaluated. When you do:
> <xsl:template match="/">
> <xsl:apply-templates select="r/a">
> <xsl:sort data-type="number" select="@at"/>
> <xsl:with-param name="p" select="position()"/>
> </xsl:apply-templates>
> </xsl:template>
The call to position() is being evaluated with the context node being
the current node in the template itself, i.e. the *root node*. It's
just as if you did:
<xsl:template match="/">
<xsl:variable name="p" select="position()" />
<xsl:apply-templates select="r/a">
<xsl:sort data-type="number" select="@at" />
<xsl:with-param name="p" select="$p" />
</xsl:apply-templates>
</xsl:template>
On the other hand, xsl:for-each *does* change the current node, to the
node that you're looking at within the current run of the loop. In
the second version of the template:
> <xsl:template match="/">
> <xsl:for-each select="r/a">
> <xsl:sort data-type="number" select="@at"/>
> <xsl:apply-templates select=".">
> <xsl:with-param name="p" select="position()"/>
> </xsl:apply-templates>
> </xsl:for-each>
> </xsl:template>
The xsl:for-each iterates over each of the a elements. Within that
xsl:for-each, the current node is an a element. Evaluating *its*
position() within the current node list gives its position. Again,
the expressions in the xsl:with-param are just as if it was evaluated
outside the xsl:apply-templates - the xsl:apply-templates doesn't
change the current node, so the above is equivalent to:
<xsl:template match="/">
<xsl:for-each select="r/a">
<xsl:sort data-type="number" select="@at" />
<xsl:variable name="p" select="position()" />
<xsl:apply-templates select=".">
<xsl:with-param name="p" select="$p" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
The simplest thing to achieve the count that you want is not to bother
with parameters at all... just do:
<xsl:template match="/">
<xsl:apply-templates select="r/a">
<xsl:sort data-type="number" select="@at" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="a">
<xsl:value-of select="position()" />,<xsl:text />
</xsl:template>
Or:
<xsl:template match="/">
<xsl:for-each select="r/a">
<xsl:sort data-type="number" select="@at" />
<xsl:value-of select="position()" />,<xsl:text />
</xsl:for-each>
</xsl:template>
I hope that helps,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
|