Subject: The value of a generic solution (Was: RE: Re: accumulate a variable...is it possible? add this )
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Wed, 9 Oct 2002 22:01:47 -0700 (PDT)
|
--- 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
|