# Selenium Webdriver, C# and accessing rows in a table

There's been other questions like these, but I feel like I'm missing some of the basics, so I'll try asking a potential duplicate question:

How do I get/list the contents of each row in a table like this?

<div class="entity-body list-entity-body entity-content-payload">
<div class="table-holder l-height-full" style="overflow-y: scroll; flex: 1 1 auto" data-bind="fullHeight: 'leave-space-for-following-elements'">
<content-placeholder class="l-height-full jsx-component-rendered" content-id="list-page-list">
<content-placeholder class=" jsx-component-rendered" content-id="standard-list-page-list">
<section class=" jsx-component-rendered" data-bind="component: { name: listCustomElementName, params: listParams }">
<table class="table-default" cellspacing="0" style="width: 100%">
<tr>
...
</tr>
<tbody>
<tr data-bind="css: { selected: $parent.selected.indexOf(href) != -1 }, loadRelated:$parent.fieldsFromRelated">>
<td class="fit-cell-content">
<a data-bind="clientHref: href" href="#/Customers/149999/Locations/000" data-server-href="/Api/Customers/149999/Locations/000">
</td>
<td class="keyColumn fit-cell-content">
<a data-bind="clientHref: href" href="#/Customers/149999/Locations/000" data-server-href="/Api/Customers/149999/Locations/000">
</td>
<td class="keyColumn fit-cell-content">
<a data-bind="clientHref: href" href="#/Customers/149999/Locations/000" data-server-href="/Api/Customers/149999/Locations/000">
</td>
<td class="keyColumn fit-cell-content">
<a data-bind="clientHref: href" href="#/Customers/149999/Locations/000" data-server-href="/Api/Customers/149999/Locations/000">
</td>
<td class="keyColumn fit-cell-content">
<a data-bind="clientHref: href" href="#/Customers/149999/Locations/000" data-server-href="/Api/Customers/149999/Locations/000">
</td>
<td class="fit-cell-content">
<a data-bind="clientHref: href" href="#/Customers/149999/Locations/000" data-server-href="/Api/Customers/149999/Locations/000">
</td>
</tr>


There are other things on the page, and this code is nested quite a but down in the tags, but it should be possible. However, one thing is finding the rows and contens (which I need hints for doing) - another is storing it and using it.

UPDATE: kirbycope has a great answer below. Building on that, how do check each row for a specific name and then click it?

UPDATE2: Using kirbycope's examples below, here's what I've got so far:

(I search the table for an row containing a specific text - "Bergen" in a td)

var table = GCDriver.Instance.FindElement(By.TagName("table"));
var rows = table.FindElements(By.TagName("tr"));

foreach (var row in rows) {
if (row.Text.Contains("Bergen")) {
//Console.WriteLine(row.Text);

var tds = row.FindElements(By.TagName("a"));
foreach (var entry in tds) {
Console.WriteLine(entry.Text);
entry.Click();
}
}


The Console.WriteLine line works fine, printing this:

149999-002
Bergen
0
0
13
Branch Office


However, the entry.Click() line does not, resulting in this error:

OpenQA.Selenium.StaleElementReferenceException: stale element reference:
element is not attached to the page document
(Session info: chrome=56.0.2924.87)
(Driver info: chromedriver=2.28.455520


Most of what I can find on that exception is that people seem to think it's because an element is not loaded, not accessible etc. on the web page, and to implement a wait or similar. But this is not the case here; I can add a timeout of 10 hours and the exception is still there. Also, if I just use the XPath of a specific row and add .Click() to that, it works fine.

UPDATE 3: As per ChatuD's help below, I'm trying this to get all the elements of a specific row (tr):

var rows = table.FindElements(By.TagName("tr"));
foreach (var row in rows) {
if (row.Text.Contains("Bergen")) {
IList<IWebElement> List = row.FindElements(By.TagName("a"));
List<String> NewList = new List<String>();

foreach (var item in List) {
}

Actions action3 = new Actions(GCDriver.Instance);
action3.MoveToElement(NewList[<Index number >]).Perform();
}


But - and pardon my lack of both C# and VS knowledge - how do I access the row element in NewList in the last line above? It doesn't work just typing the index number, and "ElementAt" doesn't exist as a method.

Get the table, then its rows, then each row's TDs, then each TD's anchor:

var table = driver.FindElement(By.TagName("table"));
var rows = table.FindElements(By.TagName("tr"));
foreach (var row in rows)
{
var rowTds = row.FindElements(By.TagName("td"));
foreach (var td in rowTds)
{
var a = td.FindElement(By.TagName("a"));
Console.WriteLine("HREF: " + a.GetAttribute("href"));
}
}


Or, if you just want each of the TDs anchors you could:

var tds = driver.FindElements(By.TagName("td"));
foreach (var td in tds)
{
var a = td.FindElement(By.TagName("a"));
var href = a.GetAttribute("href"));
if(href.Contains("Customer1234"))
{
a.Click();
break;
}
}


The takeaway here is that *.FindElements() returns a collection of elements that you can parse. In much the same way as document.querySelectorAll() does in JavaScript.

• That simple, eh? :-) – Hfrav Mar 21 '17 at 15:08
• Hm. What if you wanted to search each row for a specific name and click it? (I notice the contents are links...) – Frank H. Mar 21 '17 at 15:09
• Yes, or check the td(-s) inside the rows for specific names. – Hfrav Mar 21 '17 at 15:11
• I updated my answer. You can just grab all TDs or get all rows, then for each row, get its TDs, then for each TD get the Anchor. It all depends on what makes the most sense for you test case. – kirbycope Mar 21 '17 at 15:17
• The line "var a = td.FindElement(By.TagName("a"));" throws this exception: "threw exception: OpenQA.Selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"tag name","selector":"a"}" – Hfrav Mar 22 '17 at 9:10

As every line start with a '<a' tag

IList<IWebElement> List = driver.FindElements(By.TagName("a"));
List<String> NewList = new List<String>();
foreach (var item in List)
{
}


The you will get all the list of items in the table as NewList.

So for clicking on an element dont directly use NewList[<Index number>]. Use Actions.

Actions action3 = new Actions(Setup.driver);
action3.MoveToElement(NewList[<Index number>]).Perform();