Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old January 6th, 2008, 10:52 AM
Registered User
 
Join Date: Jan 2008
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via AIM to r2u_2
Default How to sum nodes with some intermediate process

Hi Folks,

I have small problem in calculaing total amount.

This is the scenario
[u]My XML:</u>
<EVNT>
    <EVNT_SUMM>
        <PMT_AMT>864.29</PMT_AMT>
        <CRCY_CD>25</CRCY_CD>
    </EVNT_SUMM>
    <EVNT_SUMM>
        <PMT_AMT>1032.3</PMT_AMT>
        <CRCY_CD>7978</CRCY_CD>
    </EVNT_SUMM>
    <EVNT_SUMM>
        <PMT_AMT>836.42</PMT_AMT>
        <CRCY_CD>22</CRCY_CD>
    </EVNT_SUMM>
</EVNT>


[u]My XSL:</u>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:element name="DETAILS">
            <xsl:apply-templates select="EVENT"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="EVENT">
        <xsl:element name="AMOUNT">
            <xsl:value-of select="sum(EVENT_SUMM/PMT_AMT)"/>
        </xsl:element>
    </xsl:template>
    <xsl:template name="convert">
        <xsl:param name="amt"/>
        <xsl:param name="crcy_cd"/>
        <xsl:choose>
            <xsl:when test="$crcy_cd='25'">
                <xsl:value-of select="number($amt) div 100"/>
            </xsl:when>
            <xsl:when test="$crcy_cd='22'">
                <xsl:value-of select="number($amt) div 10"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="number($amt)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>


I want to add all PMT_AMT values in EVENT_SUMM with currency conversion specified in conversion template. Currency conversion depends on CRCY_CD in EVNT_SUMM.

Can any one suggest a way to solve this problem without using any java methods.

Thanks in advance.
r2u_2
 
Old January 6th, 2008, 12:16 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

First of all note that your elements names in the sample document (e.g. EVNT_SUMM) don't match the element names in the XSLT stylesheet (e.g. EVENT_SUMM).
As for solving the problem, with XSLT 1.0 you need to write a named template calling itself, here is an example that simply includes the logic of your 'convert' template in the recursive template:
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:element name="DETAILS">
            <xsl:apply-templates select="EVNT"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="EVNT">
        <xsl:element name="AMOUNT">
            <xsl:call-template name="sum">
              <xsl:with-param name="items" select="EVNT_SUMM"/>
            </xsl:call-template>
        </xsl:element>
    </xsl:template>
    <xsl:template name="sum">
      <xsl:param name="items"/>
      <xsl:param name="total" select="0"/>
      <xsl:choose>
        <xsl:when test="$items">
          <xsl:variable name="item" select="$items[1]"/>
          <xsl:call-template name="sum">
            <xsl:with-param name="items" select="$items[position() &gt; 1]"/>
            <xsl:with-param name="total">
              <xsl:choose>
                <xsl:when test="$item/CRCY_CD = '25'">
                  <xsl:value-of select="$total + $item/PMT_AMT div 100"/>
                </xsl:when>
                <xsl:when test="$item/CRCY_CD = '22'">
                  <xsl:value-of select="$total + $item/PMT_AMT div 10"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="$total + $item/PMT_AMT"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:with-param>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$total"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
If you want to use the template you have posted then you need to adapt that code slightly:
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:element name="DETAILS">
            <xsl:apply-templates select="EVNT"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="EVNT">
        <xsl:element name="AMOUNT">
            <xsl:call-template name="sum">
              <xsl:with-param name="items" select="EVNT_SUMM"/>
            </xsl:call-template>
        </xsl:element>
    </xsl:template>
    <xsl:template name="sum">
      <xsl:param name="items"/>
      <xsl:param name="total" select="0"/>
      <xsl:choose>
        <xsl:when test="$items">
          <xsl:variable name="item" select="$items[1]"/>
          <xsl:variable name="value">
            <xsl:call-template name="convert">
              <xsl:with-param name="amt" select="$item/PMT_AMT"/>
              <xsl:with-param name="crcy_cd" select="$item/CRCY_CD"/>
            </xsl:call-template>
          </xsl:variable>
          <xsl:call-template name="sum">
            <xsl:with-param name="items" select="$items[position() &gt; 1]"/>
            <xsl:with-param name="total" select="$total + $value"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$total"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>
    <xsl:template name="convert">
        <xsl:param name="amt"/>
        <xsl:param name="crcy_cd"/>
        <xsl:choose>
            <xsl:when test="$crcy_cd='25'">
                <xsl:value-of select="number($amt) div 100"/>
            </xsl:when>
            <xsl:when test="$crcy_cd='22'">
                <xsl:value-of select="number($amt) div 10"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="number($amt)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
 
Old January 6th, 2008, 06:07 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Best solution is to use XSLT 2.0:

<xsl:value-of select="sum(EVNT_SUMM/f:convert(PRT_AMT, CRCY_CD))"/>

where f:convert is your named template converted to a function.

Here are some other ideas if you are stuck with 1.0:

http://biglist.com/lists/xsl-list/ar.../msg00968.html

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old January 7th, 2008, 01:41 AM
Registered User
 
Join Date: Jan 2008
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via AIM to r2u_2
Default

Thanks for your timely answers.
Your answers gave me new ideas to work on...
I'll let you know if i still have any concerns.





Similar Threads
Thread Thread Starter Forum Replies Last Post
beginning to intermediate to professional. shegxzyl PHP FAQs 1 May 14th, 2009 10:49 AM
Removing duplicate nodes post-process QuickSilver002 XSLT 3 April 4th, 2007 03:47 PM
intermediate storage sarah lee ASP.NET 1.0 and 1.1 Basics 3 September 11th, 2006 01:31 PM
XSL-help-sum of nodes baed on a condition skumar80 XSLT 2 November 8th, 2003 10:08 AM
Beginner, intermediate or Pro? psychadelic Beginning VB 6 5 June 17th, 2003 12:14 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.