| Subject: Re: [xsl] 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
| Current Thread | 
|---|
| 
 | 
| <- Previous | Index | Next -> | 
|---|---|---|
| [xsl] question about position(), Denis Kranjcec | Thread | Re: [xsl] question about position(), Oliver Becker | 
| Re: [xsl] Variables, Jeni Tennison | Date | Re: [xsl] Two input xml files.., Jeni Tennison | 
| Month |