This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RE: Summing a Calculation


Thanks, Jeni.  I appreciate your thoughts very much.  I see the distinction
you make with the two approaches to nesting and agree they're cleaner.
Thanks for taking the time to explain.

- Mark

-----Original Message-----
From: Jeni Tennison [mailto:mail@jenitennison.com]
Sent: Thursday, June 21, 2001 11:14 PM
To: Mark Swardstrom
Cc: 'xsl-list@lists.mulberrytech.com'
Subject: Re: [xsl] Summing a Calculation


Hi Mark,

> I need to multiply each line by the quantity to get the amount per item.
[snip]
> Here's my current solution, but would like to reduce:

Your current solution looks pretty good.  Personally, I'd *either* use
a matching template that traversed the item elements using the
following-sibling:: axis *or* use a named template that took a node
set as a parameter and walked over that by splitting it into the
'first' and 'rest'.  Your solution mixes the two approaches.

Just to show you what I mean, here's a matching template approach:

<xsl:template match="item" mode="calcTotal">
   <xsl:param name="subtotal" select="0" />
   <xsl:variable name="total"
                 select="$subtotal + (price * quantity)" />
   <xsl:choose>
      <xsl:when test="not(following-sibling::item)">
         <xsl:value-of select="$total" />
      </xsl:when>
      <xsl:otherwise>
         <xsl:apply-templates select="following-sibling::item[1]"
                              mode="calcTotal">
            <xsl:with-param name="subtotal" select="$total" />
         </xsl:apply-templates>
      </xsl:otherwise>
   </xsl:choose>
</xsl:template>

And you'd use it like:

  <xsl:variable name="total">
     <xsl:apply-templates select="item[1]" />
  </xsl:variable>
  <xsl:value-of select="format-number($total, '$#,##0.00')"/>

And here's the named template approach:

<xsl:template name="calcTotal">
   <xsl:param name="nodes" select="/.." />
   <xsl:param name="subtotal" select="0" />
   <xsl:variable name="total"
      select="$subtotal + ($nodes[1]/price * $nodes[1]/quantity)" />
   <xsl:choose>
      <xsl:when test="not($nodes[2])">
         <xsl:value-of select="$total" />
      </xsl:when>
      <xsl:otherwise>
         <xsl:call-template name="calcTotal">
            <xsl:with-param name="nodes"
                            select="$nodes[position() > 1]" />
            <xsl:with-param name="subtotal"
                            select="$total" />
         </xsl:call-template>
      </xsl:otherwise>
   </xsl:choose>
</xsl:template>

And you'd use it like:

  <xsl:variable name="total">
     <xsl:call-template name="calcTotal">
        <xsl:with-param name="nodes" select="item" />
     </xsl:call-template>
  </xsl:variable>
  <xsl:value-of select="format-number($total, '$#,##0.00')"/>

Personally, I prefer the matching template approach because it's
shorter and easier to call. However, it has the disadvantage of being
very closely tied to the source XML - it uses the fact that the nodes
you're summing are sibling item elements. The named template is more
generic because it can use any node set, and you could make it even
more so by having the calculated value (i.e. price * quantity in this
case) for a node be calculated in a separate template (or even in a
user-defined function if you like that kind of thing).  How specific
or generic you want to make it obviously depends on your goals for the
stylesheet.
  
Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]