Select nodes based on count of values

Discussion in 'XML' started by Larry R, Sep 28, 2005.

  1. Larry R

    Larry R Guest

    I am trying to use XPath (XSLT 1.0), EXSLT 1.1 (.Net) to select the
    nodelist consisting of the 'top n' nodes. THe counter
    is the count of item/value[ fieldName].

    Using a traditional for-each logic, the psuedo code would look
    something like this

    counter=0
    maxItems=4
    nodelist = nothing

    for each root/item
    counter = counter + count(value/fieldName)
    if counter < maxItems
    nodelist.add (current() ) //adds this node to the nodelist
    else
    exit for
    end if

    next item


    What I would expect of the above code is to return a nodeset consisting
    of <item>s id 1 & 2. item id=3 was not included because it's children
    made the counter exceed maxItems. Note, the item id value is only used
    for reference.

    Any help would be greatly appreciated by "One Less Bald Guy" :)

    Thanks-
    Larry

    =================================================
    <root>
    <item id="1">
    <value name="fieldName" instance="1">Alpha</value>
    <value name="fieldName" instance="2">Beta</value>
    </item>
    <item id="2">
    <value name="fieldName" instance="1">Charlie</value>
    </item>
    <item id="3">
    <value name="fieldName" instance="1">Delta</value>
    <value name="fieldName" instance="2">Echo</value>
    </item>
    </root>
    Larry R, Sep 28, 2005
    #1
    1. Advertising

  2. Larry R

    Peter Flynn Guest

    Larry R wrote:

    > I am trying to use XPath (XSLT 1.0), EXSLT 1.1 (.Net) to select the
    > nodelist consisting of the 'top n' nodes. THe counter
    > is the count of item/value[ fieldName].
    >
    > Using a traditional for-each logic, the psuedo code would look
    > something like this
    >
    > counter=0
    > maxItems=4
    > nodelist = nothing
    >
    > for each root/item
    > counter = counter + count(value/fieldName)
    > if counter < maxItems
    > nodelist.add (current() ) //adds this node to the nodelist
    > else
    > exit for
    > end if
    >


    If you want to use the items in their document order, then the
    XSLT below will do this.

    If you want to use the items in a sorted order it gets rather
    more complex.

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

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

    <xsl:variable name="maxval">
    <xsl:text>4</xsl:text>
    </xsl:variable>

    <xsl:template match="/">
    <xsl:apply-templates
    select="root/item
    [sum(value/@instance)+
    sum(preceding::value/@instance) &lt;= $maxval]"/>
    </xsl:template>

    <xsl:template match="item">
    <xsl:value-of select="@id"/>
    </xsl:template>

    </xsl:stylesheet>

    ///Peter

    >
    >
    > What I would expect of the above code is to return a nodeset consisting
    > of <item>s id 1 & 2. item id=3 was not included because it's children
    > made the counter exceed maxItems. Note, the item id value is only used
    > for reference.
    >
    > Any help would be greatly appreciated by "One Less Bald Guy" :)
    >
    > Thanks-
    > Larry
    >
    > =================================================
    > <root>
    > <item id="1">
    > <value name="fieldName" instance="1">Alpha</value>
    > <value name="fieldName" instance="2">Beta</value>
    > </item>
    > <item id="2">
    > <value name="fieldName" instance="1">Charlie</value>
    > </item>
    > <item id="3">
    > <value name="fieldName" instance="1">Delta</value>
    > <value name="fieldName" instance="2">Echo</value>
    > </item>
    > </root>
    Peter Flynn, Sep 29, 2005
    #2
    1. Advertising

  3. Larry R

    Larry R Guest

    Peter- Thank you for the quick reply.
    OK, what I was looking for was to return the nodes that were less than
    count(item/value[@name='fieldName']) < $maxval. I was wondering if the
    exslt set:leading() function might be of help here, but I do not have
    enough experience with the sets.
    Larry R, Sep 29, 2005
    #3
  4. Larry R

    Larry R Guest

    Upon review, the 'best' solution would probably be to find the
    position() of the node where the total number of preceding
    value[@name='fieldName'] = $maxItems. THAT would be some cool XSL in my
    world :)
    Larry R, Sep 29, 2005
    #4
  5. Larry R

    Peter Flynn Guest

    Larry R wrote:

    > Peter- Thank you for the quick reply.
    > OK, what I was looking for was to return the nodes that were less than
    > count(item/value[@name='fieldName']) < $maxval.


    But that is exactly what the XPath expression in my example does:

    root/item
    [sum(value/@instance)+
    sum(preceding::value/@instance) &lt;= $maxval]

    For your data, this nodeset contains the first two "item" element nodes.

    If you wanted the "value" element nodes contained within them instead,
    just add "/value" to the expression.

    ///Peter
    Peter Flynn, Sep 29, 2005
    #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. asd
    Replies:
    3
    Views:
    436
    Arnaud Berger
    May 23, 2005
  2. gavnosis
    Replies:
    0
    Views:
    512
    gavnosis
    Aug 2, 2003
  3. Timo Nentwig

    selecting nodes between other nodes

    Timo Nentwig, Jun 16, 2004, in forum: XML
    Replies:
    1
    Views:
    401
    Patrick TJ McPhee
    Jun 17, 2004
  4. Johnny Ooi

    Looking A Nodes From Within Nodes

    Johnny Ooi, Nov 13, 2004, in forum: XML
    Replies:
    10
    Views:
    653
    Johnny Ooi
    Nov 14, 2004
  5. Replies:
    2
    Views:
    868
Loading...

Share This Page