Reputation: 13
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
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
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