I'm using Selenium 2.12. Using the WebDriver API, let's say I have a WebElement that represents a table (<table>
). Using that element, how do I select all the td's in the first column? I'm assuming an xpath expression is in order here.
To better understand the table structure, if I get the HTML from my tableElement WebElement ...
String html = (String)((JavascriptExecutor)driver).executeScript("return arguments[0].innerHTML;", tableElt);
I get the jumble below. The key thing to notice is that there are 6 tr's and 16 td's ...
<thead><tr><th colspan="1" class="GCSPOWVGE GCSPOWVEE GCSPOWVEF GCSPOWVFF"><div style="padding-left: 17px;position:relative;zoom:1;"><div style="left:0px;margin-top:-4px;position:absolute;top:50%;line-height:0px;"><img onload='this.__gwtLastUnhandledEvent="load";' src="http://localhost:9080/cme-productplus-web/productplus/clear.cache.gif" style="width: 11px; height: 7px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAAiklEQVR42mNgwALyKrumFRf3iDAQAvmVXVVAxf/zKjq341WYV95hk1fZ+R+MK8C4HqtCkLW5FZ2PQYpyK6AaKjv/5VV1OmIozq3s3AFR0AXFUNMrO5/lV7WKI6yv6mxCksSGDyTU13Mw5JV2qeaWd54FWn0BRAMlLgPZl/NAuBKMz+dWdF0H2hwCAPwcZIjfOFLHAAAAAElFTkSuQmCC) no-repeat 0px 0px;" border="0"></div><div>GUID</div></div></th><th colspan="1" class="GCSPOWVGE GCSPOWVEF">Fung Ratio</th><th colspan="1" class="GCSPOWVGE GCSPOWVEF">Fung type</th><th colspan="1" class="GCSPOWVGE GCSPOWVEF">Fung Date Offset</th><th colspan="1" class="GCSPOWVGE GCSPOWVEF GCSPOWVOE">Days To Retain</th></tr></thead><colgroup><col><col><col><col><col></colgroup><tbody><tr onclick="" class="GCSPOWVAE"><td class="GCSPOWVPD GCSPOWVBE GCSPOWVCE"><div style="outline:none;" tabindex="0"> DSSUAQR6IE6E </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;"> 10 </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;"> </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;"> </div></td><td class="GCSPOWVPD GCSPOWVBE GCSPOWVME"><div style="outline:none;"> </div></td></tr><tr onclick="" class="GCSPOWVAF"><td class="GCSPOWVPD GCSPOWVBF GCSPOWVCE"><div style="outline:none;"> ETTUAQR6IE6E </div></td><td class="GCSPOWVPD GCSPOWVBF"><div style="outline:none;"> 30 </div></td><td class="GCSPOWVPD GCSPOWVBF"><div style="outline:none;"> </div></td><td class="GCSPOWVPD GCSPOWVBF"><div style="outline:none;"> </div></td><td class="GCSPOWVPD GCSPOWVBF GCSPOWVME"><div style="outline:none;"> </div></td></tr><tr onclick="" class="GCSPOWVAE"><td class="GCSPOWVPD GCSPOWVBE GCSPOWVCE"><div style="outline:none;"> FCCUAQR6IE6E </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;"> 20 </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;"> </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;"> </div></td><td class="GCSPOWVPD GCSPOWVBE GCSPOWVME"><div style="outline:none;"> </div></td></tr></tbody><tbody style="display: none;"><tr><td colspan="5" align="center"><div><div style="width: 100%; height: 100%; padding: 0px; margin: 0px; display: none;"><div style="width: 100%; height: 100%; display: none;"></div></div><div style="width: 100%; height: 100%; padding: 0px; margin: 0px; display: none;"><div class="GCSPOWVPE" style="width: 100%; height: 100%; display: none;"><img class="gwt-Image" onload='this.__gwtLastUnhandledEvent="load";' src="http://localhost:9080/cme-productplus-web/productplus/clear.cache.gif" style="width: 43px; height: 11px; background: url(data:image/gif;base64,R0lGODlhKwALAPEAAP///0tKSqampktKSiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAKwALAAACMoSOCMuW2diD88UKG95W88uF4DaGWFmhZid93pq+pwxnLUnXh8ou+sSz+T64oCAyTBUAACH5BAkKAAAALAAAAAArAAsAAAI9xI4IyyAPYWOxmoTHrHzzmGHe94xkmJifyqFKQ0pwLLgHa82xrekkDrIBZRQab1jyfY7KTtPimixiUsevAAAh+QQJCgAAACwAAAAAKwALAAACPYSOCMswD2FjqZpqW9xv4g8KE7d54XmMpNSgqLoOpgvC60xjNonnyc7p+VKamKw1zDCMR8rp8pksYlKorgAAIfkECQoAAAAsAAAAACsACwAAAkCEjgjLltnYmJS6Bxt+sfq5ZUyoNJ9HHlEqdCfFrqn7DrE2m7Wdj/2y45FkQ13t5itKdshFExC8YCLOEBX6AhQAADsAAAAAAAAAAAA=) no-repeat 0px 0px;" border="0"></div></div></div></td></tr></tbody><tfoot style="display: none;"><tr><th colspan="5" class="GCSPOWVFE GCSPOWVDE GCSPOWVNE"></th></tr></tfoot>
Sadly, both these expressions do not yield the correct results.
// This returns zero td's
final List<WebElement> tds = tableElt.findElements(By.xpath("/tr/td[1]"));
...
// This returns 238 td's (I think that's everything in my document)
final List<WebElement> tds = tableElt.findElements(By.xpath("//td[1]"));
11) Using first-of-type CSS Selector in Selenium You can use “Tag:first-of-type”. It will select the first tag element.
We can extract all the options in a dropdown in Selenium with the help of Select class which has the getOptions() method. This retrieves all the options on a Select tag and returns a list of web elements.
// This returns 238 td's (I think that's everything in my document) final List<WebElement> tds = tableElt.findElements(By.xpath("//td[1]"));
This is exactly as per thw XPath W3c Spec and is one of the most FAQ in XPath.
The precedence (priority) of the //
pseudo-operator is less than that of the []
operator.
Therefore, //SomeName[1]
selects all elements named SomeName
that are the first SomeName
child of their parent -- and there may be many such elements.
If you want to select the 1st SomeName
element in the XML document, you need to explicitly override the default operator precedence using brackets:
(//SomeName)[1]
In this case you only want the first td
descendant of a given element -- therefore in addition to the above correction, you must correct your expression to be relative -- not absolute. An absolute XPath expression (starting with /
is always evaluated having as aditional context node the document node).
Use:
(.//td)[1]
If you need all td
descendants of the current node selected, then use:
.//td
And even better:
.//descendant::td
The exact expression to use depends on the actual structure of your document.
In the most general case -- selecting all of the first-column cells from a table -- you could use the following expression:
<path_to_table>//td[1]
For example, on this document:
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
<tr>
<td>i</td>
<td>ii</td>
<td>iii</td>
<td>iv</td>
</tr>
</table>
This expression:
/table//td[1]
Gives:
<td>1</td>
<td>a</td>
<td>i</td>
Note that I'm using the descendant-or-self axis (//
) because HTML tables allow optional grouping elements (e.g. <tbody>
), which may or may not be there. However, this will include the first-column cells from nested tables, as well. Consider this input:
<table>
<tr>
<td>1</td>
<td><table><td>test</td></table></td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
<tr>
<td>i</td>
<td>ii</td>
<td>iii</td>
<td>iv</td>
</tr>
</table>
The same expression from above returns:
<td>1</td>
<td>test</td>
<td>a</td>
<td>i</td>
If you know more about your specific table structure, then you can write a more specific expression. For example, on the previous input, this expression:
/table/tr/td[1]
...returns only cells from the outermost table:
<td>1</td>
<td>a</td>
<td>i</td>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With