Home > Software design >  How to select nodes by condition EXCEPT the one with specified index
How to select nodes by condition EXCEPT the one with specified index

Time:08-03

Based on this question let's say we have XML

<root>
  <a default="False">1</a>
  <a default="True">2</a>
  <a default="False">3</a>
  <a default="False">4</a>
  <a default="True">5</a>
  <a default="False">6</a>
  <a default="False">7</a>
</root>

I can select the first node with @default="True" with

//a[@default="True"][1]  # node with value "2"

the second one with

//a[@default="True"][2]  # node with value "5"

...but if I want to select all except the first one

//a[not(self::a[@default="True"][1])]

1 2 3 4 5 6 7 &extract=//a[not(self::a[@default="True"][1])]&extract-kind=xpath3.1&printed-node-format=html&output-format=adhoc&input-format=auto&dot-notation=unambiguous" rel="nofollow noreferrer">it excludes both node with value "2" and "5"

So what's wrong with the last XPath expression? Why it ignores the index?

CodePudding user response:

To select all except the first, use

//a[@default="True"][position() != 1]

What's wrong with your expression? Well self::a only selects one node, so self::a[1] means exactly the same as self::a.

Incidentally, using //a[1] is usually wrong - it should usually be (//a)[1]. It only works in your case because all the a elements are siblings at the same level.

CodePudding user response:

Try this XPath-1.0 expression:

//a[@default='True'][count(preceding-sibling::a[@default='True'])>0]

This expression selects all a elements with at least one predecessor matching the given criteria.


The explanation why your expression //a[not(self::a[@default="True"][1])] doesn't work is simple: nearly all a elements do not satisfy the condition given. The expression selects all as that are not an a with the attribute @default with the value "True".

  • Related