5

I want to avoid using XPath where possible when finding elements in webdriver, but be able to reference child elements from already found elements e.g.

For the following html:

<div id="myelement">
    <table class="myclass">
       <tbody>
           <tr>
               <td>something</td>
               <td>
                   <table>
                       <tbody>
                           ...
                       </tbody>
                   </table>
               </td>
           </tr>
           <tr>
               ...
           </tr>
       </tbody>
    </table>
</div>

I have a css expression:

driver.find_elements('div#myelement table.myclass > tbody > tr')

I want to break this up into the table element and the rows, without having to refer back to the table expression. e.g. for XPath:

table = driver.find_element(:xpath, "//div[@id='myelement']//table[@classname='myclass']")

rows = table.find_elements(:xpath, 'tbody/tr')

I've tried the following, which works using JQuery $('div#myelement table.myclass').find('> tbody > tr')

table = driver.find_element(:css, 'div#myelement table.myclass')

rows = table.find_elements(:css, '> tbody > tr')

This causes an error `assert_ok': An invalid or illegal string was specified (Selenium::WebDriver::Error::UnknownError)

Removing the first '>' of course works, however means decendant tbody's are selected and not just immediate children.

How can I do this correctly using just css?

4
  • Does this table.find_elements(:xpath, 'tbody/tr') work? Commented Aug 25, 2013 at 14:03
  • Can you show your final purpose of the test? Commented Aug 25, 2013 at 14:04
  • As mentioned above, it works, but I'd prefer not to use xpath for one-off issues. Commented Aug 25, 2013 at 14:04
  • @BillyChan the only purpose is so I can wrap the table in a PageObject (or at least a widget), and have the object handle the fetching of rows. I'm not really using webdriver as a test, but a robot to pull data from a website. Commented Aug 25, 2013 at 14:06

1 Answer 1

5

As you don't give the page url,I took this Chinese language.Now I tried to find out the table column values for the second row of the first table having class name "wikitable sortable.

require 'selenium-webdriver'

driver = Selenium::WebDriver.for :firefox
driver.navigate.to "http://en.wikipedia.org/wiki/Chinese_language"

table = driver.find_element(:css,"table.wikitable") # !> assigned but unused variable - table
tb_col = driver.find_elements(:css,"tr:nth-of-type(2)>td")
tb_col[0..5].each{|e| p e.text}
# >> "汉语/漢語 or 中文\nHànyǔ or Zhōngwén"
# >> "汉语"
# >> "中文"
# >> "Wu\nNotes: includes Shanghainese"
# >> "Wu; 吴/吳"
# >> "Wúyǔ"

The way you tried table.find_elements(:css, '> tbody > tr') is not valid css syntax in selenium-webdriver.It should be table.find_elements(:css, 'tbody > tr').I would suggest you to write this way:

table = driver.find_element(:css, 'div#myelement table.myclass>tbody')
rows = table.find_elements(:css, 'tr')

or jsfiddle

table = driver.find_element(:css, 'div#myelement table.myclass')
rows = table.find_elements(:css, 'tbody:nth-of-type(1) > tr')
Sign up to request clarification or add additional context in comments.

6 Comments

As mentioned in the question, table.find_elements(:css, 'tbody > tr') will select descendants and not just children, e.g. there may be another table inside that table, which shouldn't also be selected.
try driver.find_element(:css, 'div#myelement table.myclass>tbody') and table.find_elements(:css, 'tr')
yes table.find_elements(:css, 'tbody:nth-of-type(1) > tr') will work I think, although not exactly the same meaning, but without me crawling webdriver server source to see if there's a way to have child selectors at the start, it's the best answer, so if you put that in a new answer, I'll accept it
@Andy which one you want me to put as an answer... I am confused :(
table.find_elements(:css, 'tbody:nth-of-type(1) > tr'), you removed it from your comments
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.