2

I've a dynamically generated iframe element (input type) and need to store it as a variable. The iframe looks like:

<iframe id="iframe39993" class="green tea" src="...foo"> 
 #document
 <!doctype html>
  <html>
   <head>...</head>
    <body style>
      <div id="layout" class=container>
        <div class="row">
          <input class="required" type="number">
         </div>
       </div>
     </body>
    </html>

I'm using Selenium/Webdriver to do this:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.switch_to.frame(driver.find_element_by_class_name('green tea'))
content = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//* [@id='layout']/div[1]/input")))
print(content.text)
driver.switch_to.default_content()
driver.quit()

For some reason I get only a newline (empty string) as output. I'm pretty sure, that the xpath should be correct, but can't print (or store) the iframe element. The iframe element contains already user input data, which I need to access. Someone any ideas?

3
  • what's the error? Commented Jan 4, 2020 at 5:34
  • Updated the question. Had a typo error, after re-checking the code I get just a newline without any errors. Commented Jan 4, 2020 at 5:38
  • I can also copy the iframe content with ActionChains, but only paste them inside the browser. Need the input as a variable, unfortunately. Commented Jan 4, 2020 at 5:42

2 Answers 2

2

Your locator .find_element_by_class_name('green tea') will not work because .find_element_by_class_name() takes only a single class name and you have passed it two, "green" and "tea". If you want to locate the element using both classes, a better choice would be a CSS selector, .green.tea.

The other issue is that INPUT elements don't contain text, they contain values. To get the value from an INPUT, you will need to use .get_attribute('value') instead of .text.

Updating your code based on the two items above,

driver = webdriver.Chrome()
driver.switch_to.frame(driver.find_element_by_css_selector('.green.tea'))
content = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//*[@id='layout']/div[1]/input")))
print(content.get_attribute('value'))
driver.switch_to.default_content()
driver.quit()

Some CSS selector references:
W3C
Selenium Tips: CSS Selectors
Taming Advanced CSS Selectors

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much! That totally solves my problem. I've copy+pasted the input with keystrokes over key_send and used it with clipboard to paste as value, but your way is more elegant.
0

The <input> tag which you are trying to locate:

<input class="required" type="number">

Doesn't have any text or innerHTML as such. So the line of code:

print(content.text)

will always print an empty string.

Here you can find a relevant discussion on Ways to deal with #document under iframe

5 Comments

Thank you, sir. That totally explains it! The iframe textbox itself isn't empty. Is there a way to access it?
@robscure As it is an <input> tag, of coarse you can click() and send_keys() in it.
That's a nice idea, I played a bit around with that. I can copy the input of the iframe with send_keys(). But how can I store that as a variable? I need to validate it inside the python code. Thanks for your time.
@robscure You don't copy the text or innerHTML of an <input> tag, rather you send text within the element. As you are sending the text yourself, you can validate it when the text (which you have sent) is processed by the Web Application and gets reflected somewhere within the webpage.
I see. I thought I could store it directly as a variable. Thank you!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.