So in a previous post I mentioned that I create objects which I call ControlObjects and a few of you told me that you do too and some of you call them Elements.

Would like to thank Adam Goucher for including it on a “Smattering of Selenium”.

So I mentioned I would share a some of them, so here is the first, its a Table ControlObject. My companies application has a financial section, with extended use of dynamic tables, so those lead to this object.

Before I created this object I found myself using a lot of XPath to read data from the table, and as we all know its not the most robust method for retrieving elements, however when you have a table, its hard to interact with a specific row/column unless it has a unique identifier which is rare.

So, I thought what if I can add some logic to my XPath calls, so that I was confident I was getting the cell I wanted.
A well structured HTML table consists of <table>/<thead></th> for the table headers and <table><tbody><tr><td> for the row and cells structure, so a standard XPath call would read: “table/tbody/tr[4]/td[3]” with the numbers being the required row / cell.

So what if I could determine those numbers using information I knew, then I could be assured I was always getting the cell I wanted, so here is how I achieved it.

I created a new object which took a table element as its parameter, then I create two lists, one for the headers (th) and one for the rows (tr), using By.Tagname, this then allows to me to inspect these lists for information I know, which in turn I can use to create an XPath request to retrieve the required cell / row.

So the standard structure of our tables is column headers across the top and the first column being a unique value such as a cost code / Id.

So I know the name of the unique column is “Cost Code”, I can then iterate through my column headers list to find the IWebElement text that equals “Cost Code”, I can then get the index of that element in the list, +1 (this is important as Lists are 0 indexed, Xpath isn’t) which gives me the correct td[x] value.

Then I can loop through the row list, using XPath to find the row that matches my unique value. So lets say that returned as 1.

Then from that match, I can do the same again to get the index of the column I want to read from, so lets say thats 5, then use XPath again to return the cell I was looking for.

So XPath can be useful especially if used Dynamically.

To note this will work if the table doesn’t have a thead area, however the first row which would contain all the th tags would be counted and looped through when looking for rows.

I have added the project to my GitHub account so please do download and have a look, and hopefully will be useful to some of you.

The project contains the ControlObject along with a set of tests to show it working. The tests are NUnit tests and use FirefoxDriver, and use the table below.

Company Contact Country
Alfreds Futterkiste Maria Anders Germany
Berglunds snabbköp Christina Berglund Sweden
Centro comercial Moctezuma Francisco Chang Mexico
Ernst Handel Roland Mendel Austria
Island Trading Helen Bennett UK
Königlich Essen Philip Cramer Germany
Laughing Bacchus Winecellars Yoshi Tannamuri Canada
Magazzini Alimentari Riuniti Giovanni Rovelli Italy
North/South Simon Crowther UK
Paris spécialités Marie Bertrand France
The Big Cheese Liz Nixon USA
Vaffeljernet Palle Ibsen Denmark

Comments