Transforming with XSLT, Grouping elements until difference found.

Discussion in 'XML' started by Jody Greening, Jan 6, 2005.

  1. Transforming with XSLT, Grouping elements until difference found.

    I am seeking some help with the following problem, I am fairly new at
    XSLT transformations, and my problem may lie in looking at it from a
    traditional programming point of view.

    I have did quite a bit of searching but have found no answers to my
    particular problem... please read below XML for the problem I am
    having.

    PS: I have no control over the XML I am trying to transform.

    --- I have only spaced the lines for clarity ---

    <Amounts>
    <Amount date="2004-05-30">5290</Amount>
    <Amount date="2004-06-30">5290</Amount>

    <Amount date="2004-07-30">5300</Amount>
    <Amount date="2004-08-30">5300</Amount>

    <Amount date="2004-09-30">5290</Amount>
    <Amount date="2004-10-30">5290</Amount>
    <Amount date="2004-11-30">5290</Amount>

    <Amount date="2004-12-30">1000</Amount>

    <Amount date="2005-01-30">5290</Amount>

    <Amount date="2005-02-28">5300</Amount>

    <Amount date="2005-03-30">5290</Amount>
    <Amount date="2005-04-30">5290</Amount>

    <Amount date="2004-07-30">5300</Amount>
    <Amount date="2004-08-30">5300</Amount>
    </Amounts>

    I am looking to transform the above XML into the below structure
    grouping payments with alike ones util there is a different payment
    encountered. I also need to inculde a count of the like payments.

    Output should look like this: (in the correct order found in the input
    stream) I have had limited success with for-each but the problem lies
    in the counting of the LIKE elements.

    <Payments>
    <Payment amount="5290" numpayments="2" />
    <Payment amount="5300" numpayments="2" />
    <Payment amount="5290" numpayments="3" />
    <Payment amount="1000" numpayments="1" />
    <Payment amount="5290" numpayments="1" />
    <Payment amount="5300" numpayments="1" />
    <Payment amount="5290" numpayments="2" />
    <Payment amount="5300" numpayments="2" />
    </Payments>

    Any help would be greatly appreciated.
    Jody Greening
    jgreening#AT#cyence#DOT#com
     
    Jody Greening, Jan 6, 2005
    #1
    1. Advertising

  2. Jody Greening wrote:

    > Transforming with XSLT, Grouping elements until difference found.
    >
    > I am seeking some help with the following problem, I am fairly new at
    > XSLT transformations, and my problem may lie in looking at it from a
    > traditional programming point of view.
    >
    > I have did quite a bit of searching but have found no answers to my
    > particular problem


    Grouping is described here:
    <http://www.jenitennison.com/xslt/grouping/index.html>

    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
     
    Martin Honnen, Jan 6, 2005
    #2
    1. Advertising

  3. I have already looked through those examples, but I did not find
    anything that can answer my above question. Maybe I am not seeing it,
    but there is no example there of what I am trying to accomplish.

    I have figured out a way to lop and see if the current value is the
    same as the previous, but I am still having the problem of counting
    them.

    Keep in mind that the outputs here are strictly for testing purposes.

    <xsl:template match="Results/Stream[@name='Rents']/Amounts/Amount">
    <xsl:for-each select="." >
    <xsl:variable name="PreviousAmount"
    select="preceding-sibling::Amount[position()=1]" />
    <xsl:variable name="CurrentAmount" select="." />
    <xsl:choose>
    <xsl:when test="scripts:CheckIfNull($CurrentAmount, '0') =
    scripts:CheckIfNull($PreviousAmount, '0')">
    <TransPaymentInfo>
    <xsl:attribute name="TransSubScheduleId">
    <xsl:text>Same as last one </xsl:text>
    | Current Payment - <xsl:value-of
    select="scripts:CheckIfNull($CurrentAmount, 'BLANK')" />
    | Previous Payment - <xsl:value-of
    select="scripts:CheckIfNull($PreviousAmount, 'BLANK')" />
    </xsl:attribute>
    </TransPaymentInfo>
    </xsl:when>
    <xsl:eek:therwise>
    <TransPaymentInfo>
    <xsl:attribute name="TransSubScheduleId">
    <xsl:text>Different than last one </xsl:text>
    | Current Payment - <xsl:value-of
    select="scripts:CheckIfNull($CurrentAmount, 'BLANK')" />
    | Previous Payment - <xsl:value-of
    select="scripts:CheckIfNull($PreviousAmount, 'BLANK')" />
    </xsl:attribute>
    </TransPaymentInfo>
    </xsl:eek:therwise>
    </xsl:choose>
    </xsl:for-each>
    </xsl:template>
     
    Jody Greening, Jan 6, 2005
    #3
  4. Jody Greening

    Joris Gillis Guest

    Hi,

    > I am looking to transform the above XML into the below structure
    > grouping payments with alike ones util there is a different payment
    > encountered. I also need to inculde a count of the like payments.
    >


    The following sample stylesheet produces the output you want.
    <?xml version='1.0' encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:eek:utput method="xml" indent="yes"/>


    <xsl:template match="Amounts">
    <Payments>
    <xsl:apply-templates select="Amount[position()= 1 or . !=preceding::Amount[1]]"/>
    </Payments>
    </xsl:template>

    <xsl:template match="Amount">
    <xsl:variable name="count" select="count(following::Amount[. !=current()][1]/preceding::Amount) "/>
    <xsl:variable name="cnt">
    <xsl:if test="$count =0"><xsl:value-of select="count(../Amount)"/></xsl:if>
    <xsl:if test="$count !=0"><xsl:value-of select="$count"/></xsl:if>
    </xsl:variable>
    <Payment amount="{.}" numpayments="{$cnt - count(preceding::Amount) }" />
    </xsl:template>

    </xsl:stylesheet>

    regards,
    --
    Joris Gillis (http://www.ticalc.org/cgi-bin/acct-view.cgi?userid=38041)
    Ceterum censeo XML omnibus esse utendum
     
    Joris Gillis, Jan 6, 2005
    #4
  5. Jody Greening wrote:

    > I have already looked through those examples, but I did not find
    > anything that can answer my above question. Maybe I am not seeing it,
    > but there is no example there of what I am trying to accomplish.


    To group you set up a key, then you can run through the elements, all
    explained here
    <http://www.jenitennison.com/xslt/grouping/muenchian.html>
    To count nodes you use the count function of XPath:


    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:eek:utput method="xml" encoding="UTF-8" indent="yes" />

    <xsl:key name="same-amount" match="Amount" use="." />

    <xsl:template match="/">
    <Payments>
    <xsl:for-each select="Amounts/Amount[generate-id() =
    generate-id(key('same-amount', .))]">
    <Payment amount="{.}" numpayments="{count(key('same-amount', .))}" />
    </xsl:for-each>
    </Payments>
    </xsl:template>

    </xsl:stylesheet>

    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
     
    Martin Honnen, Jan 6, 2005
    #5
  6. This code (Joris's) works perfectly to organize and count elements in
    the way that I explained above.

    Thanks :)
     
    Jody Greening, Jan 6, 2005
    #6
    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. Ken Adams
    Replies:
    1
    Views:
    708
    Arnaud Berger
    Mar 10, 2005
  2. Bernd Fuhrmann
    Replies:
    0
    Views:
    440
    Bernd Fuhrmann
    Feb 12, 2004
  3. Jody Greening
    Replies:
    0
    Views:
    340
    Jody Greening
    Jan 6, 2005
  4. Replies:
    2
    Views:
    474
    David Carlisle
    Feb 1, 2005
  5. Harry George

    Codesample for xml/xslt transforming

    Harry George, Sep 9, 2003, in forum: Python
    Replies:
    8
    Views:
    415
    Axel Straschil
    Sep 10, 2003
Loading...

Share This Page