Home > Net >  Concise xpath query doesn't work using Selenium Python
Concise xpath query doesn't work using Selenium Python

Time:08-21

The first xpath query works, but the second does not:

First set:

FieldElementParent_obj = Driver.find_element(by=By.XPATH, value="//div[contains(text(), '%s')]/following-sibling::div" % FieldTitle)
FieldElement_obj = FieldElementParent_obj.find_element(by=By.XPATH, value=".//div[contains(text(), '" FieldData "')]")

Second set:

FieldElementTitle_obj = Driver.find_element(by=By.XPATH, value="//div[contains(text(), '%s')]" % FieldTitle)
FieldElement_obj = FieldElementTitle_obj.find_element(by=By.XPATH, value="./following-sibling/descendant::div[contains(text(), '" FieldData "')]")

Why not?

CodePudding user response:

In the second line of the second block the xpath is missing the reference node, which you can mention as self as follows:

FieldElementTitle_obj = Driver.find_element(by=By.XPATH, value="//div[contains(text(), '%s')]" % FieldTitle)
FieldElement_obj = FieldElementTitle_obj.find_element(by=By.XPATH, value=".//self::following-sibling/descendant::div[contains(text(), '" FieldData "')]")

CodePudding user response:

Short version:

Your locators are different in the two sets (see the long version for a detailed comparison), that's why they might not act the same. At lot of it will depend on the structure of the DOM you are using them against.

Long version:

In your two "sets", you are splitting a locator into two parts and searching for them separately. If you combine each into a single locator and then compare, you can see the difference. NOTE: I turned

//div[contains(text(), '%s')] % FieldTitle

into

//div[contains(text(), '" FieldTitle "')]

for ease of comparing but they both work the same.

First set:

//div[contains(text(), '" FieldTitle "')]/following-sibling::div//div[contains(text(), '" FieldData "')]

Second set:

//div[contains(text(), '" FieldTitle "')]/following-sibling/descendant::div[contains(text(), '" FieldData "')]

In the Second set, you don't specify what element type (e.g. DIV) the following-sibling should be so you'll get whatever is the first sibling... it might be a DIV, it might not but it will depend on the structure of the DOM.

The next difference is //div vs /descendant::div. These will act the same unless the current node is a DIV... so, again it depends on your DOM. From the spec:

// is short for /descendant-or-self::node()

See the spec for more info.

  • Related