Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath: Select self and following sibling together

Tags:

html

xpath

<div>
    <dt>
        Test 1
    </dt>
    <dd>
    </dd>
    <dt>
        Test 2
    </dt>
    <dd>
    </dd>
</div>

I have this XPath written so far

//dt[contains(text(), "Test")]/self::dt|following-sibling::dd

But this is not bringing both dt and dd but just dt.

like image 570
Umair A. Avatar asked May 16 '13 09:05

Umair A.


People also ask

How can I reach sibling in XPath?

We can use the XPath following sibling axis to find this. So, for this scenario, the XPath expression will be. And we need to identify its sibling “div ” element, as shown below. However, if numerous siblings have the same node, XPath will recognise all of the different elements.

What is preceding sibling XPath?

The preceding-sibling axis indicates all the nodes that have the same parent as the context node and appear before the context node in the source document.

What is the use of self in XPath?

The self axis indicates the context node itself. It can be abbreviated as a single period ( . ).


2 Answers

If it must be a single XPath 1.0 expression then you'll have to say

//dt[contains(., 'Test')] | //dt[contains(., 'Test')]/following-sibling::dd[1]

The final [1] is important, as without that it would extract all dd elements that follow a dt containing "Test", i.e. given

<div>
    <dt>
        Test 1
    </dt>
    <dd>
        Foo
    </dd>
    <dt>
        Something else 2
    </dt>
    <dd>
        Bar
    </dd>
</div>

the version without the [1] would match three nodes, the dt containing "Test 1" and both the "Foo" and "Bar" dd elements. With the [1] you would correctly get only "Test 1" and "Foo".

But depending on exactly how you're using the XPath it may be clearer to first select

//dt[contains(., 'Test')]

and then iterate over the nodes that this matches, and evaluate

. | following-sibling::dd[1]

in the context of each of those nodes in turn.

like image 111
Ian Roberts Avatar answered Sep 28 '22 21:09

Ian Roberts


When using XPath 2.0:

//dt[contains(text(), "Test")]/(self::dt, following-sibling::dd)
like image 38
Jens Erat Avatar answered Sep 28 '22 20:09

Jens Erat