xsl-list
[Top] [All Lists]

The value of a generic solution (Was: RE: Re: accumulate a variable...is it possible? add this )

2002-10-09 22:01:47

--- Maesen, Edward  wrote:
 
Here's a solution using a recursive template. The main thing to
define
when
writing a recursive template is a proper stop condition that always
will be
met. Often times the recursive template has two parameters: one to
contain
intermediate states of something that eventually will lead to the
stop
condition, and one for intermediate states of the desired end result.
See
the comments in the stylesheet templates below, that should make
things
clearer.

XSL templates:
==============

<xsl:template match="num">
      <xsl:text>
       num=</xsl:text>
      <xsl:value-of select="."/> 
      <xsl:text>  accumulated=</xsl:text>
      <!-- to calculate sum of current and previous sibling nodes, define 
              nodeset containing those previous nodes and call 
              recursive template -->
      <xsl:variable name="nodeset" select="preceding-sibling::num"/>
      <xsl:call-template name="accumulate">
              <!-- input params for named template:
                      sum = the value of the current node 
                      nodeset = nodeset containing the previous sibling
nodes -->
              <xsl:with-param name="sum" select="."/>
              <xsl:with-param name="nodeset" select="$nodeset"/>
      </xsl:call-template>
</xsl:template>

<!-- recursive template -->
<xsl:template name="accumulate">
      <xsl:param name="sum"/>
      <xsl:param name="nodeset"/>
      <xsl:choose>
              <!-- define appropriate stop condition -->
              <xsl:when test="$nodeset">
                      <!-- stop condition is not yet met, call self with
new values 
                        for sum and nodeset params:
                              sum = previous sum + value of first node in
nodeset
                              nodeset = previous nodeset minus the first
node (this 
                              ensures that eventually the stop condition
will be met) -->
                      <xsl:call-template name="accumulate">
                              <xsl:with-param name="sum" 
      
select="number($nodeset[position()=1]) + $sum"/>
                              <xsl:with-param name="nodeset" 
                                      select="$nodeset[position()!=1]"/>
                      </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                      <!-- stop condition is met, so output the result -->
                      <xsl:value-of select="$sum"/>
              </xsl:otherwise>
      </xsl:choose>
</xsl:template>

XML Input:
==========

<numbers>
      <num>3</num>
      <num>7</num>
      <num>11</num>
      <num>6</num>
      <num>3</num>
</numbers>

Output:
=======

       num=3  accumulated=3
       num=7  accumulated=10
       num=11  accumulated=21
       num=6  accumulated=27
       num=3  accumulated=30

Edward


Thank you Edward,

Having to write such code on every single occasion will be time
consuming and error-prone -- not too-many people will be able to do it.

This is why generic templates as "scanl" are so valuable -- they
capture reliably and once for all the high level of expertise that is
necessry to write such code.

The user has only to provide the necessary parameters -- the node-set
to be processed and the one node-at a time incremental calculating
template.

This hides complexity, is convenient and easy to use, ultimately saves
time and effort.

 

=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL

__________________________________________________
Do you Yahoo!?
Faith Hill - Exclusive Performances, Videos & More
http://faith.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>
  • The value of a generic solution (Was: RE: Re: accumulate a variable...is it possible? add this ), Dimitre Novatchev <=