Home > Software design >  How to get all direct child elements of current element via CSS Selectors?
How to get all direct child elements of current element via CSS Selectors?

Time:02-06

I'd like to get all child elements of some specific element with Selenium. Let's say I have the following HTML:

<html>
  <table>
    <tr>
      <td>Test 1</td>
      <td id="123">Test <b>2</b>
        <span>span_text</span>
      </td>
      <td>Test 3</td>
    </tr>
  </table>
</html>

First, I'd like to find the second td element by its id and then I'd like to find all of its child elements (i.e. the b and span elements). Finding the second td element isn't hard:

from selenium import webdriver
from selenium.webdriver.common.by import By

page_source = """<table> 
                   <tr>
                        <td>Test 1</td>
                        <td id="123">Test<b>2</b><span>span_text</span></td>
                        <td>Test 3</td>
                   </tr> 
                 </table>
                 """

driver = webdriver.Chrome()
driver.execute_script('document.documentElement.innerHTML=arguments[0]', f"<html>{page_source}</html>")

element = driver.find_element(By.ID, "123")

In order to find the child elements, I tried the td > * CSS Selector:

for elements in element.find_elements(By.CSS_SELECTOR, f"td > *"):
    print(element.tag_name)

However, this prints two td tags instead of b and span. I also tried the . > * CSS Selector instead, which seems to be invalid. How I can select all (direct) child elements of an WebElement in Selenium by CSS Selectors?

Note: I want to use the element.find_elements() method, i.e. I want selenium to only search within the already found element.

CodePudding user response:

You were almost there. Your code is perfect. You just need to keep a track that within for statement in each iteration the decendants are referred as elements. So you have to invoke:

print(elements.tag_name) # instead of element, it should be elements

Here is the complete program:

page_source = """<table> 
           <tr>
            <td>Test 1</td>
            <td id="123">Test<b>2</b><span>span_text</span></td>
            <td>Test 3</td>
           </tr> 
         </table>
         """

driver = webdriver.Chrome(service=s, options=options)
driver.execute_script('document.documentElement.innerHTML=arguments[0]', f"<html>{page_source}</html>")
element = driver.find_element(By.ID, "123")
for elements in element.find_elements(By.CSS_SELECTOR, f"td > *"):
    print(elements.tag_name)
    

Output:

b
span

CodePudding user response:

There's a bug in your code :)

for elements in element.find_elements(By.CSS_SELECTOR, f"td > *"):
    print(element.tag_name)
                ^ elements

This should be elements.tag_name (plural of element) to use the loop variable, elements. Your variable on the previous line is element so you were printing the TD from the previous line twice.

Having said that, you can do this in a single step and simplify your code and save a little time

for element in driver.find_elements(By.CSS_SELECTOR, "[id='123'] > *"):
    print(element.tag_name)
  • Related