Select nodes based on count of values

L

Larry R

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>
 
P

Peter Flynn

Larry said:
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
 
L

Larry R

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.
 
L

Larry R

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 :)
 
P

Peter Flynn

Larry said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top