Re: [xsl] Traversing the tree

Subject: Re: [xsl] Traversing the tree
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Mon, 12 Sep 2005 20:53:59 +1000
On 9/11/05, Michael Kay <mike@xxxxxxxxxxxx> wrote:
> This kind of problem is best tackled using recursion. It's difficult to
> write your first recursive stylesheet, but it's a very powerful technique
to
> have under your belt.
>
> Basically you need to write a template that processes one of the siblings,
> passing it the value of your "counter" or "running-total" as a parameter.
> The template needs to make whatever changes are necessary to the counter or
> running total, then make a recursive call to process the next element if
> there is one, passing the new value of the counter or running total as a
> parameter. When the final sibling is reached, you return (or write to the
> output) the final value of the counter.
>
> You can do this either with call-template or apply-templates (perhaps using
> a special mode). I find it easier to use apply-templates, for two reasons:
> (a) the current node is passed as an implicit parameter, and (b) the
> recursion often terminates naturally when there are no more siblings.
>
> Here's an example that totals @price*@qty over a set of sibling elements:
>
> <xsl:template match="order">
>  <total-value>
>    <xsl:apply-template select="order-item[1]">
>      <xsl:with-param name="running-total" select="0"/>
>    </xsl:apply-templates>
>  </total-value>
> </xsl:template>
>
> <xsl:template match="order-item">
>  <xsl:param name="running-total"/>
>  <xsl:choose>
>    <xsl:when test="following-sibling::order-item">
>    <xsl:apply-template select="following-sibling::order-item[1]">
>      <xsl:with-param name="running-total" select="$running-total +
> (@price*@qty)"/>
>    </xsl:apply-templates>
>    </xsl:when>
>    <xsl:otherwise>
>      <xsl:value-of select="$running-total + (@price*@qty)"/>
>    </xsl:otherwise>
>  </xsl:choose>
> </xsl:template>


Or using FXSL:

      <xsl:value-of select=
      "f:foldl(f:add(),
               0,
               f:zipWith(f:mult(),/*/*/@price, /*/*/@qty)
               )"/>


Cheers,
Dimitre Novatchev

Current Thread