This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: question about position()
- To: "Denis Kranjcec" <denis dot kranjcec at zpm dot fer dot hr>
- Subject: Re: [xsl] question about position()
- From: Jeni Tennison <mail at jenitennison dot com>
- Date: Thu, 17 May 2001 14:51:59 +0100
- CC: "Xsl-List" <xsl-list at lists dot mulberrytech dot com>
- Organization: Jeni Tennison Consulting Ltd
- References: <KKEOLFIOLBIKEADHELGPAEOECIAA.denis.kranjcec@zpm.fer.hr>
- Reply-To: xsl-list at lists dot mulberrytech dot com
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