xslt challenging situation related to iterations

Discussion in 'XML' started by hilz, Feb 13, 2006.

  1. hilz

    hilz Guest

    Hi all
    I have this situation where I have an xml file similar to this:

    <Root>
    <MyElement year="2004"><Amount>10</Amount></MyElement>
    <MyElement year="2004"><Amount>11</Amount></MyElement>
    <MyElement year="2005"><Amount>15</Amount></MyElement>
    <MyElement year="2006"><Amount>4</Amount></MyElement>
    <MyElement year="2006"><Amount>7</Amount></MyElement>
    <MyElement year="2004"><Amount>20</Amount></MyElement>
    ...
    ...
    </Root>


    Now I want to summarize this by transforming it into something like this

    <Root>
    <MyElement year="2004">
    <Amounnt>10</Amount>
    <Amounnt>11</Amount>
    <Amounnt>20</Amount>
    </MyElement>
    <MyElement year="2005">
    <Amounnt>15</Amount>
    </MyElement>
    <MyElement year="2006">
    <Amounnt>4</Amount>
    <Amounnt>7</Amount>
    </MyElement>
    </Root>


    The problem I am having is how to loop through the MyElement elements
    and get all amounts for a given unique year, then go to the next year.
    In other words, I want to be able to use the year as a unique key for my
    iterations.

    Any help is greatly appreciated.
    Thanks
     
    hilz, Feb 13, 2006
    #1
    1. Advertising

  2. hilz wrote:


    > <Root>
    > <MyElement year="2004"><Amount>10</Amount></MyElement>
    > <MyElement year="2004"><Amount>11</Amount></MyElement>
    > <MyElement year="2005"><Amount>15</Amount></MyElement>


    > <Root>
    > <MyElement year="2004">
    > <Amounnt>10</Amount>
    > <Amounnt>11</Amount>
    > <Amounnt>20</Amount>



    > The problem I am having is how to loop through the MyElement elements
    > and get all amounts for a given unique year, then go to the next year.
    > In other words, I want to be able to use the year as a unique key for my
    > iterations.


    Then define a key and use if for grouping:

    <?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" indent="yes" />

    <xsl:key name="elementByYear" match="MyElement" use="@year" />

    <xsl:template match="Root">
    <xsl:copy>
    <xsl:apply-templates select="MyElement[generate-id() =
    generate-id(key('elementByYear', @year)[1])]" />
    </xsl:copy>
    </xsl:template>

    <xsl:template match="MyElement">
    <xsl:copy>
    <xsl:apply-templates select="@*" />
    <xsl:apply-templates select="key('elementByYear', @year)/Amount" />
    </xsl:copy>
    </xsl:template>

    <xsl:template match="@* | node()">
    <xsl:copy>
    <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
    </xsl:template>

    </xsl:stylesheet>



    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
     
    Martin Honnen, Feb 13, 2006
    #2
    1. Advertising

  3. > <xsl:apply-templates select="MyElement[generate-id() =
    > generate-id(key('elementByYear', @year)[1])]" />


    For those who haven't seen this trick before, it may be worth explaining...

    The expression "generate-id(node1)=generate-id(node2): is a way of
    testing whether node1 and node2 are the same node... often a useful
    test, but one that accidentally got let out of XSLT 1.0.

    In this case, we're checking it against the list of nodes keyed by the
    same @year value -- specifically, against the first node in that list.
    The result is that we process all the possible key values, but only the
    first node for each key. This gives us a way to enumerate the keys,
    which also got left out of XSLT 1.0.

    Then, in the template for that node, we can retrieve and process
    everything associated with that key.

    Clever solution, and it has become a standard XSLT idiom... but it's
    definitely not obvious to a beginner!


    --
    () ASCII Ribbon Campaign | Joe Kesselman
    /\ Stamp out HTML e-mail! | System architexture and kinetic poetry
     
    Joe Kesselman, Feb 14, 2006
    #3
  4. hilz

    hilz Guest

    Joe Kesselman wrote:
    >> <xsl:apply-templates select="MyElement[generate-id() =
    >> generate-id(key('elementByYear', @year)[1])]" />

    >
    > For those who haven't seen this trick before, it may be worth explaining...
    >
    > The expression "generate-id(node1)=generate-id(node2): is a way of
    > testing whether node1 and node2 are the same node... often a useful
    > test, but one that accidentally got let out of XSLT 1.0.
    >
    > In this case, we're checking it against the list of nodes keyed by the
    > same @year value -- specifically, against the first node in that list.
    > The result is that we process all the possible key values, but only the
    > first node for each key. This gives us a way to enumerate the keys,
    > which also got left out of XSLT 1.0.
    >
    > Then, in the template for that node, we can retrieve and process
    > everything associated with that key.
    >
    > Clever solution, and it has become a standard XSLT idiom... but it's
    > definitely not obvious to a beginner!
    >
    >



    Thank you Joe and Martin.
    You've given me what is necessary for me to proceed.
    I also found this example while searching. I guess it is the same as
    what Martin suggested:

    http://www.jenitennison.com/xslt/grouping/muenchian.html


    thanks
     
    hilz, Feb 14, 2006
    #4
  5. hilz

    Andy Dingley Guest

    On Mon, 13 Feb 2006 21:45:53 -0500, Joe Kesselman
    <> wrote:

    >Clever solution, and it has become a standard XSLT idiom... but it's
    >definitely not obvious to a beginner!


    Is _anything_ in XSLT obvious to a beginner? I've never known a
    language like it for needing a "cookbook" approach.

    OTOH, I'm just starting to learn Scheme.... :cool:
     
    Andy Dingley, Feb 16, 2006
    #5
  6. Andy Dingley wrote:
    > Is _anything_ in XSLT obvious to a beginner? I've never known a
    > language like it for needing a "cookbook" approach.


    Depends on what languages the beginner has been exposed to in the past.
    Most folks have only been taught procedural programming, and thinking in
    terms of pattern-matching and recursion comes hard until you get used to it.


    --
    () ASCII Ribbon Campaign | Joe Kesselman
    /\ Stamp out HTML e-mail! | System architexture and kinetic poetry
     
    Joe Kesselman, Feb 16, 2006
    #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. Gordon Macleod

    Struts iterations

    Gordon Macleod, Jul 21, 2003, in forum: Java
    Replies:
    0
    Views:
    411
    Gordon Macleod
    Jul 21, 2003
  2. Infiniti

    Do something every x iterations

    Infiniti, Jul 7, 2003, in forum: XML
    Replies:
    6
    Views:
    989
    Marrow
    Jul 8, 2003
  3. Derek Basch

    Counting iterations

    Derek Basch, Apr 8, 2005, in forum: Python
    Replies:
    11
    Views:
    582
    Andrew Dalke
    Apr 11, 2005
  4. Derek Basch

    Counting nested loop iterations

    Derek Basch, Mar 16, 2006, in forum: Python
    Replies:
    18
    Views:
    842
    Scott David Daniels
    Mar 17, 2006
  5. vertigo
    Replies:
    1
    Views:
    271
    Gabriel Genellina
    Jan 2, 2007
Loading...

Share This Page