tcarano
tcarano

Reputation: 13

XPath following-sibling expression appears to return child text and not following-sibling node

I am trying to construct an xpath expression that evaluates XML code and then matches only if the current paragraph is followed by a numbered list.

Here's my XML:

<para><b>Some text</b></para>
<numlist>
  <numlitem><para>List item #1</para></numlitem>
  <numlitem><para>List item #2</para></numlitem>
  <numlitem><para>List item #3</para></numlitem>
</numlitem>

The xpath expression I am using is:

para[following-sibling::*[1]=numlist]

However, this does not return true. If I evaluate the following xpath expression

para[following-sibling::*[1]

the result is "Some text". However since <b> is a child of <para>, I wouldn't expect these results.

The following expression returns true

para[following-sibling::numlist]

so I know it's seeing the numlist as a following sibling, but I only want it to return true if <numlist> is the first sibling following <para>.

I'm using a XML software application that applies styling based on specific contexts and conditions of elements, of which xpath can be used to determine. I'm trying to figure out if the issue is with the software (and I need to file a bug report) or if it's a problem with my xpath expression, in which I need to figure out what the correct expression would be.

Any help is greatly appreciated!

Upvotes: 1

Views: 2471

Answers (2)

Francis Avila
Francis Avila

Reputation: 31621

An element name is evaluated in the current context, so para[numlist] means "para with a child numlist element". Likewise:

para[following-sibling::*[1]=numlist]

Means "para whose first following-sibling::* has the same string value as any child numlist" element. Since the para has no numlist children, this predicate will always be false.

The equality test works with the string value of nodes, not with node identity or node name, so [element=otherelement] is almost never what you want to use.

If you want the gory details, read these paragraphs concerning boolean expressions in the XPath spec. The important one here is this:

If both objects to be compared are node-sets, then the comparison will be true if and only if there is a node in the first node-set and a node in the second node-set such that the result of performing the comparison on the string-values of the two nodes is true.

What you really mean is that the name of the following-sibling element is 'numlist':

para[name(following-sibling::*[1])='numlist']

Or:

para[following-sibling::*[1]/self::numlist]

Upvotes: 1

Kent
Kent

Reputation: 195049

1) your xml example is not well-formed.

2) try this xpath expression:

para/following-sibling::*[1][self::numlist]

the above expression just match nodes, if you want a boolean result, you need the boolean() function:

boolean(para/following-sibling::*[1][self::numlist])

Upvotes: 0

Related Questions