XPath: Choose Yourself and Next Brother

<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 does not bring both dt and dd , but just dt .

+4
source share
5 answers

If it should be a single XPath 1.0 expression, you will have to say

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

The final [1] important, since without it it extracts all dd elements that follow the dt containing "Test", ie Considering

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

the version without [1] will correspond to three nodes, dt containing "Test 1", and the elements "Foo" and "Bar" dd . With the help of [1] you correctly get only "Test 1" and "Foo".

But depending on how you use XPath, it may be clearer to choose

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

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

 . | following-sibling::dd[1] 

in the context of each of these nodes in turn.

+4
source

When using XPath 2.0:

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

Try this XPATH:

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

To avoid duplicating the contains test for the dt element, you can rewrite your query so that all the desired output elements are expressed in the search criteria only once:

 //*[contains(self::dt|self::dd/preceding-sibling::dt[1],"Test")] 

Explanation: start with the pool of all possible output elements, and from them select either dt or dd preceded by dt , where either dt matches the search.

Include this answer to show a way that reduces code duplication and makes it easier to read the expression join operator | ...

0
source

According to your example, you can use this xpath, it is shorter and simpler, but provided that you are looking for dt, and then you want ALL dt siblings (and not just the next siblings themselves). This xpath looks for the dt parent and captures all its children:

 //dt[contains(text(), "Test")]/../* 
-1
source

Source: https://habr.com/ru/post/1481132/


All Articles