Home > database >  XPATH: Different inputs for multiple elements with same xpath, based on value of parent element
XPATH: Different inputs for multiple elements with same xpath, based on value of parent element

Time:06-29

I have a relatively complex problem with xpath on Python. Here is my HTML layout:

<label name=A>
   <span name=B>
      "Your Salary"
<div name=C>
   <div name=D>
      <input name=E>

<label name=A>
   <span name=B>
      "Years of Experience"
<div name=C>
   <div name=D>
      <input name=E>

Because of the DOM, I can only ever estimate the name of input E. However, there may be multiple input Es which require different entries. My attempt was to find the title of the input at span B and base the different response inputs on that as shown here:

form_number = driver.find_elements_by_xpath('//input[contains(@name, "E")]')

for link in form_number:
    if driver.find_elements_by_xpath('//input[contains(@name, "E")]/parent::div/parent::div/preceding-sibling::label/span[1][text()[contains(., "Salary")]]'):
        link.send_keys("55000")
    else: link.send_keys("2")

The idea here being if the question has anything to do with a "salary," to input "55000." For any other question I'll settle for "2," in this case being "2 years of experience." This seems to work for the first entry, however it will apply the key (in this case 55000) to all inputs, rather than just the first. It seems like Python isn't cycling through the "if - else" loop for each element, rather taking the first condition and pasting it for every element of the list. This is the closest that I have gotten thus far.

Thank you all so much for helping me as I cut my teeth on this API!

(Edit) So after playing around a bit more... it seems like this might be a problem with the API itself. Even if I submit the default value "2" for each input, and then run the function, it will still replace both inputs to 55000. Might have to work-around this by manually iterating through the list number?

CodePudding user response:

You can take another approach to solve the issue.

First you identify the parent tags which is label and then use try..except block to check if element there then set the inputbox value else go to except block and set the other inputbox value.

#Fisrt identify the labels tag
parentTags=driver.find_elements_by_xpath('//label[@name="A"]')

#Iterate the loop
for ptag in parentTags:

   try:
      #identify the tag text of the label, if found then set the input value as 55000
      ptag.find_element_by_xpath('.//span[conains(.,"Salary")]')
      ptag.find_element_by_xpath('.//following-sibling::div[1]//input').send_keys("55000")
   except:
      #Not found then set the input value as 2
      ptag.find_element_by_xpath('.//following-sibling::div[1]//input').send_keys("2") 

CodePudding user response:

Your if driver.find_elements_by_xpath ... statement does not depend on the value of link; you will evaluate the exact same xpath once for each value of link in your loop. Presumably you should have something like link.find_elements_by_xpath (instead of driver.find_elements_by_xpath) in your if statement, in order to evaluate an xpath expression multiple times with a different context node each time (the different input elements which will appear as the sequential values of the link variable).

form_number = driver.find_elements_by_xpath('//input[contains(@name, "E")]')

for link in form_number:
    if link.find_elements_by_xpath('parent::div/parent::div/preceding-sibling::label/span[1][text()[contains(., "salary")]]'):
        link.send_keys("55000")
    else: link.send_keys("2")

Secondly, I wonder about the use of the contains function. This function tests to see if a particular string contains another string anywhere within it. e.g. contains('abc', 'b') returns true. You might just want to use the xpath = operator instead, to see if the string values are equal.

Note also that both the contains function and the = operator are case sensitive, i.e. contains("Your Salary", "salary") equals false.

form_number = driver.find_elements_by_xpath('//input[@name = "E"]')

for link in form_number:
    if link.find_elements_by_xpath('parent::div/parent::div/preceding-sibling::label/span[1][text()[contains(., "Salary")]]'):
        link.send_keys("55000")
    else: link.send_keys("2")
  • Related