1

I would like to select all <mynode> elements that have a value that appears a certain number of times (say, x) in all the elements.

Example:

<root>
  <mynode>
    <attr1>value_1</attr1>
    <attr2>value_2</attr2>
  </mynode>
  <mynode>
    <attr1>value_3</attr1>
    <attr2>value_3</attr2>
  </mynode>
  <mynode>
    <attr1>value_4</attr1>
    <attr2>value_5</attr2>
  </mynode>
  <mynode>
    <attr1>value_6</attr1>
    <attr2>value_5</attr2>
  </mynode>
</root>

In this case, I want all the <mynode> elements that whose attr2 value occurs > 1 time (x = 1). So, the last two <mynode>s.

Which query I have to perform in order to achieve this target?

LarsH
  • 27,481
  • 8
  • 94
  • 152
Baduel
  • 531
  • 3
  • 12
  • 30
  • 1
    I don't get it. Why _the last two nodes_. So I guess you refer to `mynode` at position 3 and 4. However, for both of them the attr_2 value (value_5) just appears one time in other nodes. So the example you propose does not fit to your question (or maybe I am missing or misunderstanding something) – dirkk Jun 17 '13 at 16:17
  • Yes, I meant nodes (mynode) 3 and 4. The value_5 of attr2 appears 2 times in *all* the nodes. – Baduel Jun 17 '13 at 16:21
  • @Baduel, your question says "that appear a number of times (says x) in the **other** nodes", not "in **all** nodes". Hence the confusion. – LarsH Jun 17 '13 at 20:27

2 Answers2

1

If you're using XPath 2.0 or greater, then the following will work:

for $value in distinct-values(/root/mynode/attr2)
return
    if (count(/root/mynode[attr2 = $value]) > 1) then
        /root/mynode[attr2 = $value]
    else ()

For a more detailed discussion see: XPath/XSLT nested predicates: how to get the context of outer predicate?

Community
  • 1
  • 1
Will Goring
  • 1,040
  • 1
  • 7
  • 18
0

This is also possible in plain XPath 1.0 (also works in newer versions of XPath); and probably easier to read. Think of your problem as you're looking for all <mynode/>s which have an <att2/> node that also occurs before or after the <mynode/>:

//mynode[attr2 = preceding::attr2 or attr2 = following::attr2]

If <att2/> nodes can also accour inside other elements and you do not want to test for those:

//mynode[attr2 = preceding::mynode/attr2 or attr2 = following::mynode/attr2]
Jens Erat
  • 37,523
  • 16
  • 80
  • 96