Grabbing all data values form a web table - java

I need to go through all the table values and grab those into array list (or your some suggested place)
First-row xpath list
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/th[1]
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[1]
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[2]
.
.
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[5]
2nd row, few xpaths
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[2]/th[1]
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[2]/td[1]
Please provide some Custom keyword logic for capture those values in easy way.
DOM

We can start using relative xpath for table's tbodythen we can use tagName method of By class for html tag names 'tr' and 'td' to fetch the rows and column elements
then we can save to arrayList as shown below in code.
Note - Closely observe first call to get table start is findElement and remaining are findElements as we want all elements with tr and td tagname.
#Test
public void testWebTable() {
WebElement simpleTable = driver.findElement(By.xpath("//table[1]/tbody[1]"));
// Get all rows
List<WebElement> rows = simpleTable.findElements(By.tagName("tr"));
List<String> webTableData = new ArrayList<String>();
// Print/Save data from each row
for (WebElement row : rows) {
List<WebElement> cols = row.findElements(By.tagName("td"));
for (WebElement col : cols) {
webTableData.add(col.getText());
System.out.print(col.getText() + "\t");
} System.out.println();
}
}

You can use PHP Simple HTML Dom parser library to parse those table data easily. Check out https://simplehtmldom.sourceforge.io/

Related

Finding all cells within the table instead of cells within current row in foreach loop in Java

My code is like below.
private List<WebElement> reports;
public List<WebElement> getReports(){
return Common.returnElementList(DriverFactory.getDriver(), reportsMenu, reports);
}
public Map<String, String> getReportDesc() {
Map<String, String> temp = new HashMap<>();
for(WebElement item: getReports()){
List<WebElement> cols = item.findElements(By.xpath("/child::td[#role='gridcell']"));
String key = Common.getElementText(DriverFactory.getDriver(), cols.get(0));
String desc = Common.getElementText(DriverFactory.getDriver(), cols.get(1));
temp.put(key, desc);
}
return temp;
}
With item.findElements(By.xpath("/child::td[#role='gridcell']")); I am trying to get the cells of that specific row, instead I am getting all the cells in that table.
How Can I get the specific row columns?
You need to use relative XPath locator.
Since you didn't share a link to the page containing that table we can only guess. So, I guess:
Instead of
item.findElements(By.xpath("/child::td[#role='gridcell']"));
try this:
item.findElements(By.xpath(".//td[#role='gridcell']"));
The dot . infront of the XPath means this is relative XPath, we want to locate element matching //td[#role='gridcell'] inside current node item.
Otherwise driver will search for all elements matching /child::td[#role='gridcell'] expression form the first, top element on the page.

Return all Select web elements as List in Selenium

Not a duplicate: I am not asking for the <option> within a <select>. I would like to return the <select> web elements themselves as a List. When achieved, the list should have a size of 2.
I have only found driver.findElements() that returns a List<WebElement>.
How do I return a List<Select> by ng-model="income.frequency"?
(Note: I have ngWebDriver so I can use ByAngular.model("income.frequency") as locator.)
HTML:
In order to match elements by their attribute, you can use the CSS selector:
By.cssSelector("<tag>[<attribute>='<value>']")
And in context:
List<WebElement> elements = driver.findElements(By.cssSelector("select[ng-model='income.frequency']"));
Edit: According to Selenium documentation, you can create a Select with a very straight-forward constructor. Hence, if you want a list of Select objects, just construct a new list:
List<Select> selectList = new ArrayList<>();
List<WebElement> elements = driver.findElements(By.cssSelector("select[ng-model='income.frequency']"));
for(WebElement element : elements) {
selectList.add(new Select(element);
}

Call Individual Index of WebElement List

If anyone needs reference or background here was my first question asked
Retrieving a list of WebElements and Identifying them
At this point I have retrieved a list of WebElements
#FindBy(css = "td[id^=ctl00_SomeGridData_ucControlList_trgControlList_ctl00__]")
List<WebElement> allGridData;
At this point in my code I can use the web Element to call the index for example
allGridData.get(0).click
however the list is not strictly integers for example if I access at the row level <tr> it would be:
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__0
but if I were to call a link within row they are table data <td> broken into divs that look like this:
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__ctl04_lbView
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__ctl04_hlTestPlan
or this
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__ctl07_lbView
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__ctl07_hlTestPlan
Since all the WebElements start with a common css selector
#FindBy(css = "td[id^=ctl00_SomeGridData_ucControlList_trgControlList_ctl00__]")
List<WebElement> allGridData;
how can identify a specific index that is a char value (ie ctl107) vs just an integer?
Assuming you want two lists, one for the View Details and one for the View Test Plans, you need the $ (ends with):
#FindBy(css = "a[id$=lbView]")
List<WebElement> allDetailViewLinks;
#FindBy(css = "a[id$=hlTestPlan]")
List<WebElement> allTestPlanLinks;
But my best guess is that you want to click on a link in a specific row rather than based on index in a list of Web Elements. For instance based on the text in the td in <tr id="ctl00_SoxMain_ucControlList_trgControlList_ctl00__0" class="rgRow">
<td class="rgExpandCol" valign="top"/><td valign="top">AL-01</td>.
You need a method to get the row with specific text in the td.
WebElement getRow(String specificValue) {
return driver.findElement(By.xpath("//td[text()='"+specificValue+"']"))
.findElement(By.xpath(".."));
}
Then you can make the methods for detail view and test plan view.
public void openDetailsView(String specificValue) {
getRow(specificValue)
.findElement(By.cssSelector("a[id$=lbView]"))
.click();
}
public void openTestPlanView(String specificValue) {
getRow(specificValue)
.findElement(By.cssSelector("a[id$=hlTestPlan]"))
.click();
}

Getting the count of rows from a web table - Selenium WebDriver Java

I am working on selenium webdriver using java. I am facing a problem. I have a web table and I have test case for add event functionality, that successfully adds the event in the table. Now I want to assert/verify if I got the added event in my table or not (Because if the functionality is broken, then date will not add in the table, and I can fail that test deliberately). The number of events are unknown before the start of test case. My logic for this test case verification is as follows:
Add the event in the table. The code to add event is :
public void addIndividualEvent(String eventDate, String eventName) throws Exception
{
driver.findElement(individualEventDate).sendKeys(eventDate);
driver.findElement(individualEventName).sendKeys(eventName);
driver.findElement(addIndividualEventBtn).click();
}
Now, after this step, there may be multiple events already in the table. So my next step would be to.
Find the number of rows in the table.
Construct a for loop that goes through each row and get the text of the date field.
Add the result of for loop to a list.
Then Assert.assertEquals(List,eventDate); will tell me if my added event is in the table or not.
Now, below is the HTML code of the table in my website.
<table class="table table-condensed table-hover event-list">
<tbody>
<tr class="study-event-row ng-scope" ng-repeat="event in events | orderBy:'-date'">
<tr class="study-event-row ng-scope" ng-repeat="event in events | orderBy:'-date'">
<tr class="study-event-row ng-scope" ng-repeat="event in events | orderBy:'-date'">
</tbody>
</table>
I was able to construct the xpath that highlights all my rows available in the table.
xpath = //table[#class='table table-condensed table-hover event-list']/tbody/tr
Now the issue I am facing is that I dont know how to use this xpath to get the count of rows from my table. I tried to use xpath.getSize(); but this returned the dimensions of the table and not the actual count.
Can anyone tell me how can I get the no of rows? Thanks
To get the rows, do the following-
Using CSS selector:
List<WebElement> rows = driver.findElement(By.cssSelector("[class='table table-condensed table-hover event-list'] tr"));
Or if you have to use XPATH, then do:
List<WebElement> rows = driver.findElements(By.xpath("//table[#class='table table-condensed table-hover event-list']/tbody/tr"));
This is returning a list of WebElements. You can get the count here:
int count = rows.size();
System.out.println("ROW COUNT : "+count);
Then you can get text for each element and assert if it's as expected. As you are saying the text should be same for all elements, then you can do something like this:
for(WebElement e : rows) {
assertEquals("expected text", e.getText());
}
Use the following code to get the row size of the table.
WebElement webElement=project.login.driver.findElement(By.xpath("tbodyXpath"));
List<WebElement> rows=webElement.findElements(By.xpath("tablerowXpath"));
System.out.println("Size -------"+rows.size());
Assuming your XPath works, you can just do this...
List<WebElement> rows = driver.findElements(By.xpath("//table[#class='table table-condensed table-hover event-list']/tbody/tr"));
System.out.println(rows.size());
It will return you the number of rows (TRs) in that table.
You could use the XPath:
count(//table[#class='table table-condensed table-hover event-list']//tr)
This will count all the tr elements that are descendants of the table element with #class="table table-condensed table-hover event-list"
Resolve the table object through your xpath, then use that WebElement as your SearchContext and get all TR elements within. The size of the return list should tell you your visible row count.
int EXPECTED_ROW_COUNT = 3;
/**
* Test case for counting the number of visible rows in a table.
* #see "http://stackoverflow.com/questions/33233883/getting-the-count-of-rows-from-a-web-table-selenium-webdriver-java"
* #author http://stackoverflow.com/users/5407189/jeremiah
*/
#Test
public void testCountRows() {
WebDriver wd = new FirefoxDriver();
wd.get("http://www.w3schools.com/html/tryit.asp?filename=tryhtml_table");
WebDriverWait wait = new WebDriverWait(wd, 10);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("iframeResult"));//Specific to test location # w3schools!
WebElement parentTable = wd.findElement(By.xpath("html/body/table/tbody"));
//WebElement parentTable = wd.findElement(By.xpath("//table[#class='table table-condensed table-hover event-list']/tbody"));
//Now use the parentTable as the root of the search for all 'tr' children.
List<WebElement> rows = parentTable.findElements(By.xpath("./tr"));
Assert.assertTrue(EXPECTED_ROW_COUNT == rows.size());
}
/**
* Test that you can use to direct at your url and interact with rows.
*/
#Test
public void testYourRowCount() {
WebDriver wd = new FirefoxDriver();
//FIXME
wd.get("yourURLHere");
WebElement parentTable = wd.findElement(By.xpath("//table[#class='table table-condensed table-hover event-list']/tbody"));
//Now use the parentTable as the root of the search for all 'tr' children.
List<WebElement> rows = parentTable.findElements(By.xpath("./tr"));
//FIXME: Do stuff with the rows.
}

Get data from table using jSoup

I am looking to get data from the table on http://www.sportinglife.com/greyhounds/abc-guide using jSoup. I would like to put this data into some kind of table within my java program that I can then use in my code.
I'm not too sure how to do this. I have been playing around with jSoup and currently am able to get each cell from the table to print out using a while loop - but obviously can't use this always as the number of cells in the table will change.
Document doc = Jsoup.connect("http://www.sportinglife.com/greyhounds/abc-guide").get();
int n = 0;
while (n < 100){
Element tableHeader = doc.select("td").get(n);
for( Element element : tableHeader.children() )
{
// Here you can do something with each element
System.out.println(element.text());
}
n++;
}
Any idea of how I could do this?
There are just a few things you have to implement to achieve your goal. Take a look on this Groovy script - https://gist.github.com/wololock/568b9cc402ea661de546 Now lets explain what we have here
List<Element> rows = document.select('table[id=ABC Guide] > tbody > tr')
Here we're specifying that we are interested in every row tr that is immediate child of tbody which is immediate child of table with id ABC Guide. In return you receive a list of Element objects that describes those tr rows.
Map<String, String> data = new HashMap<>()
We will store our result in a simple hash map for further evaluation e.g. putting those scraped data into the database.
for (Element row : rows) {
String dog = row.select('td:eq(0)').text()
String race = row.select('td:eq(1)').text()
data.put(dog, race)
}
Now we iterate over every Element and we select content as a text from the first cell: String dog = row.select('td:eq(0)').text() and we repeat this step to retrieve the content as a text from the second cell: String race = row.select('td:eq(1)').text(). Then we just simply put those data into the hash map. That's all.
I hope this example with provided description will help you with developing your application.
EDIT:
Java code sample - https://gist.github.com/wololock/8ccbc6bbec56ef57fc9e

Categories