Grouping problem

Discussion in 'XML' started by Mike King, Jan 6, 2005.

  1. Mike King

    Mike King Guest

    I don't know how to group the following data in the way I want it. I want
    the output of the transformation to be "5678". Does anyone know what I am
    doing worry?

    <?xml version="1.0"?>
    <data>
    <unit sn="5">
    <test-a>
    <result id="0">5</result>
    </test-a>
    <test-a>
    <result id="1">6</result>
    </test-a>
    <test-b>
    <result id="0">10</result>
    </test-b>
    </unit>
    <unit sn="6">
    <test-a>
    <result id="1">8</result>
    </test-a>
    <test-a>
    <result id="0">7</result>
    </test-a>
    <test-b>
    <result id="0">11</result>
    </test-b>
    </unit>
    </data>


    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt">
    <xsl:eek:utput method="text" />

    <xsl:template match="unit[1]">
    <xsl:apply-templates select="test-a" />
    </xsl:template>

    <xsl:template match="unit">
    <xsl:variable name="my-sort">
    <xsl:for-each select="/data/unit[1]/test-a/result">
    <xsl:value-of select="@id" />
    </xsl:for-each>
    </xsl:variable>

    <xsl:apply-templates select="test-a">
    <xsl:sort
    select="count(msxsl:node-set($my-sort)/*[string()=string(current()/result/@id)]/preceding-sibling::*)"
    data-type="number" />
    </xsl:apply-templates>
    </xsl:template>
    </xsl:stylesheet>
     
    Mike King, Jan 6, 2005
    #1
    1. Advertising

  2. I don't know how to group the following data in the way I want it. I want
    the output of the transformation to be "5678". Does anyone know what I am
    doing worry?

    I couldn't guess what grouping you were trying to do from your required
    output, so I can't suggest what xslt you need. You may want to look at
    http://www.jenitennison.com/xslt/grouping
    However I can point out some errors in your code

    <xsl:variable name="my-sort">
    <xsl:for-each select="/data/unit[1]/test-a/result">
    <xsl:value-of select="@id" />
    </xsl:for-each>

    This result tree fragment variable just consists of a single root node
    (/) with child a text node with value which is the concatenation of all
    the selected id attribute values. There are no elements.

    so when you make this into a node set

    msxsl:node-set($my-sort)

    You get a single root node equivalent to the root node of a document
    with no elements so msxsl:node-set($my-sort)/* will always be the empty
    node set.

    David
     
    David Carlisle, Jan 6, 2005
    #2
    1. Advertising

  3. Mike King

    Mike King Guest

    > I couldn't guess what grouping you were trying to do from your required
    > output, so I can't suggest what xslt you need. You may want to look at
    > http://www.jenitennison.com/xslt/grouping
    > However I can point out some errors in your code
    >
    > <xsl:variable name="my-sort">
    > <xsl:for-each select="/data/unit[1]/test-a/result">
    > <xsl:value-of select="@id" />
    > </xsl:for-each>
    >
    > This result tree fragment variable just consists of a single root node
    > (/) with child a text node with value which is the concatenation of all
    > the selected id attribute values. There are no elements.
    >
    > so when you make this into a node set
    >
    > msxsl:node-set($my-sort)
    >
    > You get a single root node equivalent to the root node of a document
    > with no elements so msxsl:node-set($my-sort)/* will always be the empty
    > node set.
    >
    > David
    >


    The problem I am having is the test-a elements are unsorted between unit
    elements. I don't care how the test-a elements are sorted as long as they
    are sorted the same way. So what I have tried to do is repeat the order of
    the first unit's test-a elements. I know the first unit will always be at
    /data/unit[1] so that's why I did that. The test-a element always has one
    result element, so I don't have to worry about concatenation. I was hoping
    $my-sort would contain a sequence of text nodes, which would allow me to
    order following test-a elements based on the first unit's test-a elements.
     
    Mike King, Jan 6, 2005
    #3
  4. "Mike King" <> writes:

    ...
    > The test-a element always has one
    > result element, so I don't have to worry about concatenation.


    But you selected more than one such element and concatenated the result.
    you get the concatenation of all the id values of result elements below
    the first unit, so "01" in your sample input.


    > I was hoping
    > $my-sort would contain a sequence of text nodes, which would allow me to
    > order following test-a elements based on the first unit's test-a elements.


    It contains a root node with child a single text node, but even if it
    did contain a sequence of text nodes (which is never possible in XPath
    1, adjacent text nodes that share a parent atre always merged)
    your Xpath of
    msxsl:node-set($my-sort)/*[....

    would select nothing as msxsl:node-set($my-sort)/* selects al the element
    children (and text nodes are not elements).

    I think that for each unit you just want to iterate through the first
    one and select children with ids in that order. You don't need
    xx:node-set for that:


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

    <xsl:eek:utput method="text" />

    <xsl:variable name="order" select="data/unit[1]/test-a/result"/>

    <xsl:template match="unit">
    unit [<xsl:value-of select="@sn"/>]
    <xsl:variable name="u" select="."/>
    <xsl:for-each select="$order/@id">
    <xsl:apply-templates select="$u/test-a/result[@id=current()]"/>
    </xsl:for-each>

    </xsl:template>
    </xsl:stylesheet>


    produces

    unit [5]
    56

    unit [6]
    78

    on your sample input.

    David
     
    David Carlisle, Jan 6, 2005
    #4
  5. Mike King

    Mike King Guest

    The following XSLT works for my test case but I don't know why. I would
    think the value of the keys needs to be the position of the test-a element
    for this to work. How can I assign the position to the keys?


    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:eek:utput method="text" />
    <xsl:key name="my-testa-order" match="/data/unit[1]/test-a/result/@id"
    use="current()" />

    <xsl:template match="unit">
    <xsl:apply-templates select="test-a">
    <xsl:sort select="key('my-testa-order', result/@id)"
    data-type="number" />
    </xsl:apply-templates>
    </xsl:template>
    </xsl:stylesheet>
     
    Mike King, Jan 6, 2005
    #5
  6. "Mike King" <> writes:

    > The following XSLT works for my test case but I don't know why.


    It works becaus eon your test file the results in teh first unit have
    unique values, that are in the same order as the id's so your sort
    values are 5 and 6 (the values of the results). If for example the
    values in the first unit had been equal then everything would get that
    sort value and no sorting woul happen.


    > I would
    > think the value of the keys needs to be the position of the test-a element
    > for this to work. How can I assign the position to the keys?



    You can't: keys always return nodes not arbitrary values (such as integer
    positions)

    You could use a sort of
    <xsl:sort select="count(key('my-testa-order', result/@id)/../../preceding-sibling::test-a)"
    but see previous reply

    David

    >
    > <?xml version="1.0"?>
    > <xsl:stylesheet version="1.0"
    > xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    > <xsl:eek:utput method="text" />
    > <xsl:key name="my-testa-order" match="/data/unit[1]/test-a/result/@id"
    > use="current()" />
    >
    > <xsl:template match="unit">
    > <xsl:apply-templates select="test-a">
    > <xsl:sort select="key('my-testa-order', result/@id)"
    > data-type="number" />
    > </xsl:apply-templates>
    > </xsl:template>
    > </xsl:stylesheet>
     
    David Carlisle, 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. Bryce (Work)

    Grouping and Sum problem

    Bryce (Work), Sep 30, 2003, in forum: XML
    Replies:
    3
    Views:
    512
    Bryce (Work)
    Oct 1, 2003
  2. virendra
    Replies:
    0
    Views:
    1,127
    virendra
    Aug 9, 2006
  3. I.M. Postor
    Replies:
    2
    Views:
    605
    I.M. Postor
    Sep 27, 2006
  4. Replies:
    8
    Views:
    501
    Simon Brooke
    Mar 23, 2007
  5. Replies:
    8
    Views:
    596
    Pavel Lepin
    Sep 13, 2007
Loading...

Share This Page