Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath for two separate paths?

I am using Selenium Webdriver to locate text on a webpage using the text's XPath. There are two separate conditions I want to look for: Span tags with class 'correct'and spans tags with a parent label from li tags with class 'answer_correction'.

There are 4 'answer_corrections' elements and 16 'correct' elements.

So far, the XPath I have come up with is:

answers = browser.find_elements_by_xpath('//li[@class="answer_correction"]/label/span' or '//span[@class="correct"]')

I think this should return a list of WebElements from both criteria.

This code:

browser.find_elements_by_xpath('//li[@class="answer_correction"]/label/span')

returns a list of 4 elements, as expected.

This code:

 browser.find_elements_by_xpath('//span[@class="correct"]')

returns a list of 16 elements, as expected.

However, when I try the XPath I created to merge the two, it returns just the web elements from the first path before the 'or'.

answers = browser.find_elements_by_xpath('//li[@class="answer_correction"]/label/span' or '//span[@class="correct"]')

returns only a list of the 4 'answer_corrections'

when I reverse the order,

answers = browser.find_elements_by_xpath('//span[@class="correct"]' or '//li[@class="answer_correction"]/label/span')

returns only the 16 'correct' elements.

This leads the to believe that something is wrong with the 'or' in the statement.

What is the correct way of merging two separate XPaths into one?

I cannot just append one list onto another as the order of there 20 elements is important.

like image 440
Peter Edmonds Avatar asked Jan 26 '26 15:01

Peter Edmonds


2 Answers

Found my own answer! The 'or' operator is not for computing 2 node sets. For that task you have to use the '|' operator. | != or. So, the correct XPath to combine the two is:

answers = browser.find_elements_by_xpath('//li[@class="answer_correction"]/label/span | //span[@class="correct"]')

This returns a list of 20 items, all in order.

like image 81
Peter Edmonds Avatar answered Jan 29 '26 05:01

Peter Edmonds


I would use a CSS selector for this. They are much shorter, easier to read, and easier to write.

li.answer_correction > label > span , span.correct

CSS selectors are faster and more widely supported. I do use XPath but only when I need to find an element by contained text which is something that only XPath can do.

CSS Selector Reference

Selenium Tips: CSS Selectors

Taming Advanced CSS Selectors

like image 34
JeffC Avatar answered Jan 29 '26 05:01

JeffC