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.