Sum over computed value ?

Discussion in 'XML' started by Thomas Zangl, Jan 10, 2006.

  1. Thomas Zangl

    Thomas Zangl Guest

    Hi!

    I have an XML like this:

    <?xml version="1.0" encoding="UTF-8"?>
    <invoice>
    <bill>
    <BId>20</BId>
    <CId>73</CId>
    <BDate>2006-01-10</BDate>
    <BStatus>0</BStatus>
    </bill>

    <billitems>

    <item>
    <PName>Kiwi</PName>
    <PPrice>0.900</PPrice>
    <PId>1</PId>
    <BCQuant>15</BCQuant>

    </item>

    <item>
    <PName>Apfel</PName>
    <PPrice>0.500</PPrice>
    <PId>3</PId>
    <BCQuant>10</BCQuant>

    </item>

    </billitems>
    </invoice>

    Now I want to have the sum of
    /invoice/billitems/item/BCQuant*/invoice/billitems/item/PPrice

    (=total price)
    Any ideas how to do?

    TIA!
    --
    ----------------------------------------------------------------
    ,yours Thomas Zangl - - http://www.tzis.net/ -
    - Freelancer - IT Consulting & Software Development -
    Use Y.A.M.C! now! Get it at http://www.borg-kindberg.ac.at/yamc/
     
    Thomas Zangl, Jan 10, 2006
    #1
    1. Advertising

  2. Thomas Zangl wrote:


    > <invoice>


    > <billitems>
    >
    > <item>
    > <PName>Kiwi</PName>
    > <PPrice>0.900</PPrice>
    > <PId>1</PId>
    > <BCQuant>15</BCQuant>
    >
    > </item>
    >
    > <item>
    > <PName>Apfel</PName>
    > <PPrice>0.500</PPrice>
    > <PId>3</PId>
    > <BCQuant>10</BCQuant>
    >
    > </item>
    >
    > </billitems>
    > </invoice>
    >
    > Now I want to have the sum of
    > /invoice/billitems/item/BCQuant*/invoice/billitems/item/PPrice


    XPath 2.0 with a for..in expression has the expressive power to do that
    easily and with one expression e.g.

    <xsl:value-of select="sum(for $item in invoice/billitems/item return
    $item/PPrice * $item/BCQuant)" />

    If you want to do it with XSLT 1.0 and XPath 1.0 then you need to write
    a recursive template where you pass in the item elements, compute the
    BCQuant * PPPrice for the first item and pass that value and the
    remaining items to the template until all items have been processed:

    <xsl:template name="computeTotal">
    <xsl:param name="items" />
    <xsl:param name="currentTotal" select="0" />
    <xsl:choose>
    <xsl:when test="$items">
    <xsl:call-template name="computeTotal">
    <xsl:with-param name="items"
    select="$items[position() &gt; 1]" />
    <xsl:with-param name="currentTotal"
    select="$items[1]/PPrice * $items[1]/BCQuant + $currentTotal" />
    </xsl:call-template>
    </xsl:when>
    <xsl:eek:therwise>
    <xsl:value-of select="$currentTotal" />
    </xsl:eek:therwise>
    </xsl:choose>
    </xsl:template>

    <xsl:template match="/">
    <html>
    <head>
    <title>sum</title>
    </head>
    <body>
    <p>Sum is:
    <xsl:call-template name="computeTotal">
    <xsl:with-param name="items"
    select="invoice/billitems/item" />
    </xsl:call-template>
    </p>
    </body>
    </html>
    </xsl:template>

    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
     
    Martin Honnen, Jan 11, 2006
    #2
    1. Advertising

  3. Just for fun, here's how to do it using xgawk (from
    http://sourceforge.net/projects/xmlgawk):

    xgawk -lxml '
    {
    switch (XMLEVENT) {
    case "STARTELEM":
    PATH = PATH"/"XMLNAME
    if (PATH == "/invoice/billitems/item")
    delete chardata
    break
    case "CHARDATA":
    if ($1 != "")
    chardata[PATH] = $0
    break
    case "ENDELEM":
    if (PATH == "/invoice/billitems/item")
    sum += chardata["/invoice/billitems/item/BCQuant"]* \
    chardata["/invoice/billitems/item/PPrice"]
    PATH = substr(PATH,1,length(PATH)-length(XMLNAME)-1)
    break
    }
    }

    END {
    printf "Sum = %.3f\n",sum
    }'
     
    Andrew Schorr, Jan 11, 2006
    #3
  4. Google for FXSL

    Cheers,
    Dimitre Novatchev

    "Thomas Zangl" <> wrote in message
    news:dq15ra$gbk$-gems.net...
    > Hi!
    >
    > I have an XML like this:
    >
    > <?xml version="1.0" encoding="UTF-8"?>
    > <invoice>
    > <bill>
    > <BId>20</BId>
    > <CId>73</CId>
    > <BDate>2006-01-10</BDate>
    > <BStatus>0</BStatus>
    > </bill>
    >
    > <billitems>
    >
    > <item>
    > <PName>Kiwi</PName>
    > <PPrice>0.900</PPrice>
    > <PId>1</PId>
    > <BCQuant>15</BCQuant>
    >
    > </item>
    >
    > <item>
    > <PName>Apfel</PName>
    > <PPrice>0.500</PPrice>
    > <PId>3</PId>
    > <BCQuant>10</BCQuant>
    >
    > </item>
    >
    > </billitems>
    > </invoice>
    >
    > Now I want to have the sum of
    > /invoice/billitems/item/BCQuant*/invoice/billitems/item/PPrice
    >
    > (=total price)
    > Any ideas how to do?
    >
    > TIA!
    > --
    > ----------------------------------------------------------------
    > ,yours Thomas Zangl - - http://www.tzis.net/ -
    > - Freelancer - IT Consulting & Software Development -
    > Use Y.A.M.C! now! Get it at http://www.borg-kindberg.ac.at/yamc/
     
    Dimitre Novatchev, Jan 12, 2006
    #4
  5. Thomas Zangl

    William Park Guest

    Thomas Zangl <> wrote:
    > Hi!
    >
    > I have an XML like this:
    >
    > <?xml version="1.0" encoding="UTF-8"?>
    > <invoice>
    > <bill>
    > <BId>20</BId>
    > <CId>73</CId>
    > <BDate>2006-01-10</BDate>
    > <BStatus>0</BStatus>
    > </bill>
    >
    > <billitems>
    >
    > <item>
    > <PName>Kiwi</PName>
    > <PPrice>0.900</PPrice>
    > <PId>1</PId>
    > <BCQuant>15</BCQuant>
    >
    > </item>
    >
    > <item>
    > <PName>Apfel</PName>
    > <PPrice>0.500</PPrice>
    > <PId>3</PId>
    > <BCQuant>10</BCQuant>
    >
    > </item>
    >
    > </billitems>
    > </invoice>
    >
    > Now I want to have the sum of
    > /invoice/billitems/item/BCQuant*/invoice/billitems/item/PPrice
    >
    > (=total price)
    > Any ideas how to do?



    You need XML parser and floating point calculator. Fortunately, Bash
    shell can do both. (See my .sig)

    start() # Usage: start tag att=value ...
    {
    case ${XML_TAG_STACK[0]} in
    item) BCQuant=0 PPrice=0 ;;
    billitems) rpn clear ;;
    esac
    }
    data() # Usage: data text
    {
    case ${XML_TAG_STACK[*]|,.} in
    BCQuant.item.billitems.invoice) BCQuant="$1" ;;
    PPrice.item.billitems.invoice) PPrice="$1" ;;
    esac
    }
    end() # Usage: end tag
    {
    case ${XML_TAG_STACK[0]} in
    item) rpn $BCQuant $PPrice x + =x ;;
    esac
    }
    expat -s start -d data -e end file.xml

    The above code will give you running sum. 'rpn' is shell builtin
    command, which is full RPN calculator (modelled after HP-42S).

    --
    William Park <>, Toronto, Canada
    ThinFlash: Linux thin-client on USB key (flash) drive
    http://home.eol.ca/~parkw/thinflash.html
    BashDiff: Super Bash shell
    http://freshmeat.net/projects/bashdiff/
     
    William Park, Jan 13, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Raymond Du

    Computed columns in datagrid

    Raymond Du, Dec 1, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    2,587
    Joe Fallon
    Dec 2, 2004
  2. John Dalberg
    Replies:
    1
    Views:
    427
    Bruce Barker
    Feb 3, 2006
  3. Replies:
    2
    Views:
    877
    Adam Maass
    May 24, 2005
  4. Pascal Steiss
    Replies:
    1
    Views:
    3,412
    Toby Inkster
    Mar 19, 2005
  5. Christian Roth
    Replies:
    2
    Views:
    408
    Dimitre Novatchev
    Dec 16, 2003
Loading...

Share This Page