Re: [xsl] Calculate balance

Subject: Re: [xsl] Calculate balance
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 11 Mar 2002 17:07:19 +0000
Hi Shabbir,

>> Or if performance is really an issue, you could take a different
>> approach in which you step through the rows one by one, with a
>> template that applies templates to the next row and passes on the
>> balance from each step. Let us know if you want to see an example
>> of how that would work.
>
> Yes, I want to know that approch.

OK. Currently, you tell the processor to iterate over all the rows at
once, with an xsl:for-each:

  <xsl:for-each select="report/ledgerbook/table/row">
    <tr>
      <td><xsl:value-of select="ledgerdate"/></td>
      <td><xsl:value-of select="voucher"/></td>
      <td><xsl:value-of select="costcenter"/></td>
      <td><xsl:value-of select="lccode"/></td>
      <td><xsl:value-of select="description"/></td>
      <xsl:call-template name="amountplace"/>
    </tr>
  </xsl:for-each>

Rather than do that, you can manually step through them one by one.
This enables you to pass parameters, keeping track of the current
balance, from one row to the next.

Instead of the xsl:for-each, then, just apply templates to the first
row in your table:

  <xsl:apply-templates select="report/ledgerbook/table/row[1]" />

Then create a template that matches row elements and takes a
parameter, $balance, which is originally set to the openingbalance:

<xsl:template match="row">
  <xsl:param name="balance" select="../../openingbalance" />
  ...
</xsl:template>

Within the template, you can work out the difference between this
balance and the previous one as I showed in the last email, and
therefore work out a new balance based on the old one:

<xsl:template match="row">
  <xsl:param name="balance" select="../../openingbalance" />
  <xsl:variable name="difference">
    <xsl:choose>
      <xsl:when test="amount/@type = 'D'">
        <xsl:value-of select="amount * -1" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="amount" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="newbalance" select="$balance + $difference" />
  ...
</xsl:template>

You can use this new balance within the tr element that you
create:

<xsl:template match="row">
  <xsl:param name="balance" select="../../openingbalance" />
  <xsl:variable name="difference">
    <xsl:choose>
      <xsl:when test="amount/@type = 'D'">
        <xsl:value-of select="amount * -1" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="amount" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="newbalance" select="$balance + $difference" />
  <tr>
    <td><xsl:value-of select="ledgerdate"/></td>
    <td><xsl:value-of select="voucher"/></td>
    <td><xsl:value-of select="costcenter"/></td>
    <td><xsl:value-of select="lccode"/></td>
    <td><xsl:value-of select="description"/></td>
    <xsl:call-template name="amountplace"/>
    <td><xsl:value-of select="$newbalance" /></td>
  </tr>
  ...
</xsl:template>

You can also use it as the value to be passed to the next row that you
process. You need to apply templates to the immediately following row
within the document, passing the value of the $newbalance variable as
the value of the $balance parameter, as follows:

<xsl:template match="row">
  <xsl:param name="balance" select="../../openingbalance" />
  <xsl:variable name="difference">
    <xsl:choose>
      <xsl:when test="amount/@type = 'D'">
        <xsl:value-of select="amount * -1" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="amount" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="newbalance" select="$balance + $difference" />
  <tr>
    <td><xsl:value-of select="ledgerdate"/></td>
    <td><xsl:value-of select="voucher"/></td>
    <td><xsl:value-of select="costcenter"/></td>
    <td><xsl:value-of select="lccode"/></td>
    <td><xsl:value-of select="description"/></td>
    <xsl:call-template name="amountplace"/>
    <td><xsl:value-of select="$newbalance" /></td>
  </tr>
  <xsl:apply-templates select="following-sibling::row[1]">
    <xsl:with-param name="balance" select="$newbalance" />
  </xsl:apply-templates>
</xsl:template>

Cheers,

Jeni

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


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


Current Thread