tags:

views:

357

answers:

3

Can I find one XML node with the most children with XPath?

<xml>
  <node id="1">
    <child />
  <node>
  <node id="2">
    <child /><child />
  <node>
  <node id="3">
    <child /><child />
  <node>
  <node id="4">
    <child /><child /><child />
  <node>
  <node id="5">
    <child /><child /><child />
  <node>
</xml>

I would like to select either node 4 or node 5 with a single, pure XPath 1.0 expression.

+1  A: 

I think that it is impossible because to count children you need function count() which has one parameter - node-set and returns count of elements in this set. So you have no option how to count more node-sets than one to get max value.

Note: I am talking about XPath 1.0

Gaim
I came to the same conclusion, but I'll leave the question open some more, maybe there *is* some clever way.
Tomalak
@Tomalak I know how to do this in XQuery, I think that XPath 2.0 also offers some way ( there are variables, cycles, ... ) but unfortunately I can't XPath 2.0 so I can't help you.
Gaim
@Gaim: The question was targeted at 1.0 anyway. I forgot to mention it, question edited.
Tomalak
+1  A: 

I also don't think this is possible (based on the fact that I haven't been able to do it :)). Of course, if you're allowed to change the xml (even just temporarily during this processing), you could update it to put the child count as an attribute on the node (or as the node value itself), after which it's easy:

/xml/node[not(../node/@childCount > ./@childCount)]

or

/xml/node[not(../node > .)]

But you probably already know that.

The other thing I thought might work was to do some clever maths along pigeon-hole principle lines, to take as inputs the total child count and the number of nodes, and produce a minimum child count that the max-node must have, and then doing

/xml/node[child[position()=formula_for_magic_number_goes_here]]

but I soon realised that I couldn't come up with such a formula that would correctly deal with all cases - for example, if there were 10 nodes with child counts of 10, 99 1, 1, (and the rest 1s too), no amount of manipulation of the numbers 27 and 10 is going to produce a cut off point that includes 10 but excludes 9.

AakashM
Thanks for trying to tackle the problem. :-) The more I think about it, the more I become convinced that this is, in fact, impossible.
Tomalak
A: 

I know this is pretty old, but if it helps anyone out, I wanted to do this and I think this works, at least it does for me:

/xml/node[count(./child) > count(following-sibling::node/child) and count(./child) > count(preceding-sibling::node/child)]

I'm not great with Xpath so maybe I'm missing something.

Ted