2

this is a simplified HTML structure i'm searching through:

<div class="main">
...other stuff...
       <td class="child">44</td>
       <td class="child">59</td>
       <td class="child">11</td>
</div>
<div class="main">
...other stuff...
       <td class="child">5</td>
       <td class="child">14</td>
       <td class="child">98</td>
</div>
...this kind of structure repeats with similar numbers a few more times but with identical class names

I need to extract all the numbers under the first found main class so I've made a query to search for the first main, and all td's with the specific class under it. Can somebody give me a hint what I'm doing wrong since this query gives me all the numbers from all td's with class "child" in all "main" div's:

List<WebElement> koefi = driver.findElements(By.xpath("//div[@class='main'][1]//td[@class='child']"));

What am I doing wrong or is my logic right but I'm missing some other parts of html which I haven't pasted here since the structure is too cumbersome..?

Thank You!!

p.s.: I tried this also but again, I get contents of all td's with "child" class, and not only the first "main"..

List<WebElement> koefi = driver.findElements(By.xpath("//*[1][@class='main']//td[@class='child']"));

UPDATE: I managed to solve my problem by first getting the first occurence of the "main" div which is by default found by the .findElement function:

WebElement element = driver.findElement(By.xpath("//*[1][@id='main']"));

And then extracting with .findElements function the "child" classes:

List<WebElement> kk = element.findElements(By.className("child"));

I am still unable to figure out why doesn't the .findElements with my xpath work, or it works too well, it extracts every "main" class and not only the first one. And the original HTML is too big to paste here, so I don't want to bother you guys!!

21
  • 1
    Do you getting any error? can you please try : java.util.List<WebElement> koefi = driver.findElements(By.xpath("//div[@class='main'][1]//td[@class='child']")); Commented Dec 23, 2014 at 9:31
  • 2
    Are you sure all <div class="main"> are siblings? Commented Dec 23, 2014 at 9:32
  • @Helping: I get a list of all the "child" elements, and my goal is to get "child" elements only under the first "main".. I imported java.util.List at the top of my file.. Commented Dec 23, 2014 at 9:47
  • @Maroun: there is an underlying structure above the "main" container but, yes they are all in the same level, for example div1>div2>div3>main, and then again div1>div2>div3>main and so on.. Commented Dec 23, 2014 at 9:50
  • 1
    The xpath in the original question //div[@class='main'][1]//td[@class='child'] contains a relative path which holds true for all your main classes. Commented Dec 23, 2014 at 14:30

2 Answers 2

1

A much cleaner solution would be to first grab all the divs with class main, like so:

List<WebElement> allDivs = driver.findElements(By.className("main"));

Then, as you specified, find all the tds with class child, like so:

List<WebElement> tds = allDivs[0].findElements(By.className("child"));

After that, it is just a matter of iterating over all the "tds" and read out your values.

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

1 Comment

this is a great approach, thanks for the idea. I did it in a similar fashion, i got the first occurence of "main" with .findelement() and them got all "child" td's with .findelements(). but thank you very much for the idea!!
0

You say in a comment that

the "main"'s are not direct siblings

so I suspect you are falling foul of a common error related to the definition of // in XPath. The path

//div[@class='main'][1]

does not select the first "main" div in the document. The reason for this is that // is a shorthand for /descendant-or-self::node()/ (including the leading and trailing slashes), so what this path actually means is

/descendant-or-self::node()/child::div[@class='main'][1]

When you see it fully expanded you realise that the [1] relates to the child:: step and not the search for descendants, i.e. you'll get all the div elements in the document that have the class "main" and are the first div-with-class-main under their respective parent elements. If your actual HTML is

<div>
  <div class="main">...</div>
</div>
<div>
  <div class="main">...</div>
</div>

then that XPath would select both of them (they're both the first under their parents). If you do just want the first one in the document then you should use the descendant:: axis

/descendant::div[@class='main'][1]

which will give you the first matching descendant only.

2 Comments

shouldn't this: //*[1][@class='main']//td[@class='child'] give me the first occurence of "main" also?
@Hrvoje85 predicates apply left to right - //*[1][@class='main'] means every element in the document that is the first child element of its parent, and has the class main, as opposed to //*[@class='main'][1] which would be every element that is the first element-with-class-main in its parent.

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.