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

Subject: The value of a generic solution (Was: RE: [xsl] 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


Current Thread