Selenium WebDriver - iteration through table rows - java

I'm having an issue with Selenium in Java.
I have a web page like this:
<html>
<body>
<div id='content'>
<table class='matches'>
<tr id='today_01'>
<td class='team-a'>Real Madrid</td>
<td class='score'>0-0</td>
<td class='team-b'>Barcelona</td>
</tr>
<tr id='today_02'>
<td class='team-a'>PSG</td>
<td class='score'>1-1</td>
<td class='team-b'>Manchester City</td>
</tr>
<tr id='today_03'>
<td class='team-a'>Liverpool</td>
<td class='score'>2-2</td>
<td class='team-b'>Arsenal</td>
</tr>
</table>
<div id='content'>
<body>
<html>
I first get all the rows into a list:
List<WebElement> allRows = driver.findElements(By.xpath("//table[#class='matches']/tbody/tr[contains(#id, 'today')]"));
Next I iterate through all the elements displaying the WebElement (i.e. the row) and on the next line I display the td containing the home team, separated by a line:
for (WebElement row : allRows) {
System.out.println("Outer HTML for row" + row.getAttribute("outerHTML"));
System.out.println("Outer HTML for Home Team cell" + row.findElement(By.xpath("//td[contains(#class,'team-a')]")).getAttribute("outerHTML"));
System.out.println("------------------------------------------------------------");
}
The first println displays all rows, one by one.
The second however displays ONLY 'Real Madrid' for each iteration. I'm losing my mind because I don't understand why. Can someone please help?
The output:
<tr id='today_01'>
<td class='team-a'>Real Madrid</td>
<td class='score'>0-0</td>
<td class='team-b'>Barcelona</td>
</tr>
<td class='team-a'>Real Madrid</td>
------------------------------------------------------------
<tr id='today_02'>
<td class='team-a'>PSG</td>
<td class='score'>1-1</td>
<td class='team-b'>Manchester City</td>
</tr>
<td class='team-a'>Real Madrid</td>
------------------------------------------------------------
<tr id='today_03'>
<td class='team-a'>Liverpool</td>
<td class='score'>2-2</td>
<td class='team-b'>Arsenal</td>
</tr>
<td class='team-a'>Real Madrid</td>
------------------------------------------------------------

You have to use like this
System.out.println("Outer HTML for Home Team cell" + row.findElement(By.xpath("td[contains(#class,'team-a')]")).getAttribute("outerHTML"));
Then it will point to the correct element that we want.

Related

How to loop through this query using Jsoup?

I want to loop through the news table and get the title and rating of each row. I tried different options, but I can’t understand why the select method receives all the options at once.
I need to get each news block in a loop.
I used this way to get table link:
Elements elements = document.select("#hnmain > tbody > tr:nth-child(3) > td > table");
This query doesn't work in a loop because it gets all the elements at once. I need to get the elements sequentially. So that I can do like this:
List list = new ArrayList<>();
for (Element element: elements){
String title = element...
String rating = element...
list.add(title);
list.add(rating);
}
Sample data from html:
<table border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr class="athing" id="33582264">
<td align="right" valign="top" class="title"><span class="rank">1.</span></td>
<td valign="top" class="votelinks">
<center>
<a id="up_33582264" href="vote?id=33582264&how=up&goto=front%3Fday%3D2022-11-13">
<div class="votearrow" title="upvote"></div></a>
</center></td>
<td class="title"><span class="titleline">Show HN: I built my own PM tool after trying Trello, Asana, ClickUp, etc.<span class="sitebit comhead"> (<span class="sitestr">upbase.io</span>)</span></span></td>
</tr>
<tr>
<td colspan="2"></td>
<td class="subtext"><span class="subline"> <span class="score" id="score_33582264">632 points</span> by tonypham <span class="age" title="2022-11-13T12:00:06">20 days ago</span> <span id="unv_33582264"></span> | hide | 456 comments </span></td>
</tr>
<tr class="spacer" style="height:5px"></tr>
<tr class="athing" id="33584941">
<td align="right" valign="top" class="title"><span class="rank">2.</span></td>
<td valign="top" class="votelinks">
<center>
<a id="up_33584941" href="vote?id=33584941&how=up&goto=front%3Fday%3D2022-11-13">
<div class="votearrow" title="upvote"></div></a>
</center></td>
<td class="title"><span class="titleline">Forking Chrome to turn HTML into SVG<span class="sitebit comhead"> (<span class="sitestr">fathy.fr</span>)</span></span></td>
</tr>
if I understand your question I think this code will work for you
Document doc = Jsoup.parse("<table border=\"0\" id=\"hnmain\" cellpadding=\"0\" cellspacing=\"0\"> <tbody> <tr class=\"athing\" id=\"33582264\"> <td align=\"right\" valign=\"top\" class=\"title\"><span class=\"rank\">1.</span></td> <td valign=\"top\" class=\"votelinks\"> <center> <a id=\"up_33582264\" href=\"vote?id=33582264&how=up&goto=front%3Fday%3D2022-11-13\"> <div class=\"votearrow\" title=\"upvote\"></div></a> </center></td> <td class=\"title\"><span class=\"titleline\">Show HN: I built my own PM tool after trying Trello, Asana, ClickUp, etc.<span class=\"sitebit comhead\"> (<span class=\"sitestr\">upbase.io</span>)</span></span></td> </tr> <tr> <td colspan=\"2\"></td> <td class=\"subtext\"><span class=\"subline\"> <span class=\"score\" id=\"score_33582264\">632 points</span> by tonypham <span class=\"age\" title=\"2022-11-13T12:00:06\">20 days ago</span> <span id=\"unv_33582264\"></span> | hide | 456 comments </span></td> </tr> <tr class=\"spacer\" style=\"height:5px\"></tr> <tr class=\"athing\" id=\"33584941\"> <td align=\"right\" valign=\"top\" class=\"title\"><span class=\"rank\">2.</span></td> <td valign=\"top\" class=\"votelinks\"> <center> <a id=\"up_33584941\" href=\"vote?id=33584941&how=up&goto=front%3Fday%3D2022-11-13\"> <div class=\"votearrow\" title=\"upvote\"></div></a> </center></td> <td class=\"title\"><span class=\"titleline\">Forking Chrome to turn HTML into SVG<span class=\"sitebit comhead\"> (<span class=\"sitestr\">fathy.fr</span>)</span></span></td> </tr>");
Elements elements = doc.select("#hnmain .athing");
for (Element element : elements) {
String title = element.select(".title").text();
String rank = element.select(".rank").text();
System.out.println(title + " -- "+rank);
}

how to extract specified values from a table with selenium based on a string condition

I have a table which has a column which contains:
a list of invoices
a column which contains a lots of charge types for every invoice displayed
What I want to do is to make a function which receives a String parameter,for example the invoice number and return all the charge types for invoice number inserted
Here is the code for the table
Every time a new invoice is displayed on the table,the first line of the table contains and a value
That value represents the number of the charge types displayed on every invoice
For example the charge types are :Management fee,Payments,Funds Transmission Cost,Acquiring Authorisation Fee,Service etc.
<form method="post" action="/accounting/billing/showInvoiceTransactionsCountTotal.html?
jlbz=lfISHfhqWHPj5fSzCwFKoP8c5ukwXecQt0fr4iL6ak" target="detail">
<table>
<tbody>
<tr>
<tr class="odd">
<td rowspan="8">
<a href="/accounting/billing/showInvoice.html?invoiceNumber=BA7123399&jlbz=lfISHfhqWHPj5fSzCwFKoP8c5ukwXecQt0fr4iL6ak">
BA7123399
<input type="hidden" value="BA7123399" name="invoiceChecked"/>
</a>
</td>
<td>Management fee (captured transactions)</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>2</td>
</tr>
<tr class="odd">
<td>Payments</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>2</td>
</tr>
<tr class="odd">
<td>Funds Transmission Cost (FTC)</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>1</td>
</tr>
<tr class="odd">
<td>Acquiring Authorisation Fees</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>2</td>
</tr>
<tr class="odd">
<td>Service</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>2</td>
</tr>
<tr class="odd">
<td>Refunds</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>1</td>
</tr>
<tr class="odd">
<td>Chargebacks</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>1</td>
</tr>
<tr class="odd">
<td>Minimum Billing</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>2</td>
</tr>
<tr class="even">
<td rowspan="4">
<a href="/accounting/billing/showInvoice.html?invoiceNumber=BA7123421&jlbz=lfISHfhqWHPj5fSzCwFKoP8c5ukwXecQt0fr4iL6ak">
BA7123421
<input type="hidden" value="BA7123421" name="invoiceChecked"/>
</a>
</td>
<td>Payments</td>
<td>ALEXAUTOMATION01</td>
<td>ALEXADCODE</td>
<td>1</td>
</tr>
<tr class="even">
<tr class="even">
<tr class="even">
<tr class="odd">
<td rowspan="8">
<a href="/accounting/billing/showInvoice.html?invoiceNumber=BA7123398&jlbz=lfISHfhqWHPj5fSzCwFKoP8c5ukwXecQt0fr4iL6ak">
BA7123398
<input type="hidden" value="BA7123398" name="invoiceChecked"/>
</a>
</td>
<td>Management fee (captured transactions)</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>1</td>
</tr>
<tr class="odd">
<tr class="odd">
<tr class="odd">
<tr class="odd">
<tr class="odd">
<tr class="odd">
<tr class="odd">
<tr class="even">
<td rowspan="10">
<a href="/accounting/billing/showInvoice.html?invoiceNumber=BA7123397&jlbz=lfISHfhqWHPj5fSzCwFKoP8c5ukwXecQt0fr4iL6ak">
BA7123397
<input type="hidden" value="BA7123397" name="invoiceChecked"/>
</a>
</td>
<td>Management fee (captured transactions)</td>
<td>PAYPALC001M2</td>
<td>PAYPALC001A1</td>
<td>2</td>
</tr>
<tr class="even">
<tr class="even">
<tr class="even">
<tr class="even">
<tr class="even">
<tr class="even">
<tr class="even">
<tr class="even">
<tr class="even">
</tbody>
You need to add some logic to achieve this scenario.since,invoice number row is missing for some of the common invoice number. Please try with the below
Algorithm:
1. Firstly,find all the row elements from the table
2. Iterate all the rowelement and match the expected Invoice Number.
3. If the Invoice Number is matched, then print all the sub sequence column charge type until next charge invoice number matches
Code:
String InvoiceNumber="";
List<String> chargetype=new ArrayList<>();
Boolean isInvoiceSpecificCharge=false;
//Find All the tr specific element
List<WebElement> elementList=driver.findElements(By.xpath("//table/tbody/tr"));
for(WebElement element:elementList){
WebElement tempElement=null;
try{
tempElement=element.findElement(By.xpath(".//a"));
}
catch(Exception e){
}
//If the Invoice Number is present, then we need to take the charge from td[2] else from td[1].
if(tempElement.getText().equalsIgnoreCase(InvoiceNumber)){
isInvoiceSpecificCharge=true;
chargetype.add(element.findElement(By.xpath(".//td[2]")).getText());
}
else if(tempElement==null && isInvoiceSpecificCharge ==true){
chargetype.add(element.findElement(By.xpath(".//td")).getText());
}else if(!tempElement.getText().equalsIgnoreCase(InvoiceNumber)){
isInvoiceSpecificCharge=false;
}
}

Closed Resultset: next error in jsp page, after upgrading to ojdbc7.jar from ojdbc14.jar via myEclipse

Creating two result sets in a Java class below & when return to the jsp page, access it below as such & then loop through the result sets to put data on the page fields.
Was working just fine with ojdbc14.jar, but now upgraded to ojdbc7.jar (for Oracle 12c) via myEclipse project. Getting a Closed Resultset: next error in the jsp page when access the first result set.
Any ideas or suggestions please with this upgrade being done?
I know I can use collections, etc., but trying to keep the code the same with this returned cursors result sets to be accessed in the jsp page. Thanks for any assistance.
jsp page:
<%
BCSData vBCS =
(BCSData)session.getAttribute("com.sherwin.barcodeshipping.bcsData");
%>
<TABLE class="data" >
<TR class="header">
<TD class="dataTxt"> Order Number </TD>
<TD class="dataTxt"> Rex </TD>
<TD class="dataTxt"> Size Code </TD>
<TD class="dataTxt"> Loc </TD>
<TD class="dataNbr"> Total Cartons </TD>
<TD class="dataNbr"> Total Pallets </TD>
<TD class="dataNbr"> Total Weight </TD>
<TD class="dataNbr"> Total Units </TD>
<TD class="dataNbr"> Order Units </TD>
<TD class="dataNbr"> Order Qty </TD>
</TR>
<%
while (vBCS.bolResultSet.next())
{
%>
<TR class="body">
<TD class="dataTxt"><%= vBCS.bolResultSet.getString(1) %> </TD>
<TD class="dataTxt"><%= vBCS.bolResultSet.getString(2) %> </TD>
<TD class="dataTxt"><%= vBCS.bolResultSet.getString(3) %> </TD>
<TD class="dataTxt"><%= vBCS.bolResultSet.getString(4) %> </TD>
<TD class="dataNbr"><%= vBCS.bolResultSet.getFloat(5) %> </TD>
<TD class="dataNbr"><%= vBCS.bolResultSet.getFloat(6) %> </TD>
<TD class="dataNbr"><%= vBCS.bolResultSet.getFloat(7) %> </TD>
<TD class="dataNbr"><%= vBCS.bolResultSet.getFloat(8) %> </TD>
<TD class="dataNbr"><%= vBCS.bolResultSet.getFloat(9) %> </TD>
<TD class="dataNbr"><%= vBCS.bolResultSet.getFloat(10) %> </TD>
</TR>
<%
}
%>
</TABLE>
<HR class="innerMed" >
<TABLE class="data">
<TR class="header">
<TD class="dataTxt"> WHS </TD>
<TD class="dataTxt"> Customer </TD>
<TD class="dataTxt"> Dock </TD>
<TD class="dataNbr"> Total Pallets </TD>
<TD class="dataNbr"> Total Weight </TD>
<TD class="dataNbr"> Total Units </TD>
</TR>
<%
while (vBCS.bolSummaryResultSet.next())
{
%>
<TR class="body">
<TD class="dataTxt"><%= vBCS.bolSummaryResultSet.getString(1)
%> </TD>
<TD class="dataTxt"><%= vBCS.bolSummaryResultSet.getString(2)
%> </TD>
<TD class="dataTxt"><%= vBCS.bolSummaryResultSet.getString(3)
%> </TD>
<TD class="dataNbr"><%= vBCS.bolSummaryResultSet.getFloat(4)
%> </TD>
<TD class="dataNbr"><%= vBCS.bolSummaryResultSet.getFloat(5)
%> </TD>
<TD class="dataNbr"><%= vBCS.bolSummaryResultSet.getFloat(6)
%> </TD>
</TR>
<%
} // while
%>
</TABLE>
Java class where the result sets were created and closed:
public ResultSet bolResultSet;
public ResultSet bolSummaryResultSet;
public Integer assignDock(String pDBSource, String pLoginID)
{
Integer vRetCode;
String vRetMsg;
Connection vConnection = null;
CallableStatement vCallStmt = null;
try
{
vConnection = DBConnection.getConnection(pDBSource, pLoginID);
//System.out.println("BCSData.java assignDock");
vCallStmt = vConnection.prepareCall
("BEGIN ship_door_assignment_pkg.assign_dock (?,?, ?,?,?,?,?,?, ?,?,?,?,?,?, ?, ?,?,?,?); END;");
vCallStmt.setString(1, plantCode);
vCallStmt.setString(2, dock);
vCallStmt.setString(3, p1.palLbl);
vCallStmt.setFloat(4, p1.cartonQty);
vCallStmt.setFloat(5, p1.palSize);
vCallStmt.setFloat(6, p1.drumGallons);
vCallStmt.setFloat(7, p1.drumGross);
vCallStmt.setFloat(8, p1.drumTare);
vCallStmt.setString(9, p2.palLbl);
vCallStmt.setFloat(10, p2.cartonQty);
vCallStmt.setFloat(11, p2.palSize);
vCallStmt.setFloat(12, p2.drumGallons);
vCallStmt.setFloat(13, p2.drumGross);
vCallStmt.setFloat(14, p2.drumTare);
vCallStmt.setString(15, printer);
vCallStmt.registerOutParameter(16, OracleTypes.NUMBER);
vCallStmt.registerOutParameter(17, OracleTypes.VARCHAR);
vCallStmt.registerOutParameter(18, OracleTypes.CURSOR);
vCallStmt.registerOutParameter(19, OracleTypes.CURSOR);
vCallStmt.execute();
vRetCode = vCallStmt.getInt(16);
vRetMsg = vCallStmt.getString(17);
if (vRetCode == 0)
{
bolSummaryResultSet = (ResultSet)vCallStmt.getObject(18);
bolResultSet = (ResultSet)vCallStmt.getObject(19);
}
else
{ errorMsg = vRetMsg;
}
}
catch (SQLException se)
{
throw new RuntimeException(se);
}
finally
{
DBConnection.closeCallableStatement(vCallStmt);
DBConnection.closeConnection(vConnection);
}
return vRetCode;
} //assignDock
It's a lifecycle problem. If you close the database connection, all related result sets are also closed. (There is no connection to the database anymore. Don't ask me why it worked before.)
So you have to change your code such that it follows this sequence:
Run stored procedure and retrieve cursor/result set
Execute JSP page
Close database connection
I couldn't find any information if the result set retrieved as an out parameter of the stored procedure lives on after the statement has been closed. I think so. If not, you also need to wait before you close the statement.
The problem is that ResultSet must be closed too, and normally before the close of the statement. That statement or the connection might close the result set. However there are flags to make the result used longer, and even separate types. However common practice is to shovel a ResultSet to some List, and use that.
Try this:
vCallStmt = vConnection.prepareCall("BEGIN ship_door_assignment_pkg.assign_dock"
+ "(?,?, ?,?,?,?,?,?, ?,?,?,?,?,?, ?, ?,?,?,?); END;",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
The last option should work.

get table span class content using jsoup

I have a website that contains a table that look like similar(bigger..) to this one:
</table>
<tr>
<td>
<table width="100%" cellspacing="-1" cellpadding="0" border="0" dir="rtl" style="padding-top: 25px;">
<tr>
<td align="right" style="padding-right: 25px;">
<span class="artist_name_txt">
name
<p class="diccografia">subname</p>
</span>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table width="100%" border="0" cellspacing="0" cellpadding="0" dir="rtl" style="padding-right: 25px; padding-left: 25px">
<tr>
<td class="songs" align="right">
number1
</td>
</tr>
<tr>
<td class="songs" align="right">
number2
.......
</td>
</tr>
</table>
and I need an idea how can i parse the website and extract this table into 2 arrays -
one will be something like names{number1, number2}
and the second will be links{number1link, number2link}
I tried a lot of ways and nothing really helps me.
You should read the JSoup Cookbook - especially the Selector syntax is very powerful.
Here's an example:
final String html = ...
// use connect().get() instead if you connect to an website
Document doc = Jsoup.parse(html);
List<String> names = new ArrayList<>();
List<String> links = new ArrayList<>();
for( Element element : doc.select("a.artist_player_songlist") )
{
names.add(element.text());
links.add(element.attr("href"));
}
System.out.println("Names: " + names);
System.out.println("Links: " + links);
Output:
Names: [number1, number2]
Links: [/number1link, /number2link]
Android Web Scraping with a Headless Browser
Htmlunit on Android application
HttpUnit/HtmlUnit equivalent for android

or condition in selenium xpath

How to implement or condition in xpath to get text inside the table td ?
From the below table, my expected output should be:
Black bean sauce
Black bean chicken
USA(New York)
India(New Delhi)
<table>
<tr class="foods foods_s-fndds2-f41205100">
<td class="name">
Black bean sauce
</td>
<td class="calories">280</td>
</tr>
<tr class="foods foods_s-fndds2-f41205140">
<td class="name">
Black bean chicken
</td>
<td class="calories">280</td>
</tr>
<tr class="foods foods_s-fndds2-f41210200">
<td class="name">
<span class="truncated">kathmandu…</span>
<span class="complete">USA(New<br>
York)</span>
</td>
</tr>
<tr class="folder foods foods_undefined">
<td class="name" colspan="4"><span></span>Black, brown, or Bayo beans, dry, cooked</td>
<td class="actions"><a class="open" href="Javascript://"></a></td>
</tr>
<tr class="foods foods_s-fndds2-f41210200">
<td class="name">
<span class="truncated">kathmandu…</span>
<span class="complete">India(New<br>
Delhi)</span>
</td>
</tr>
</table>
i tried this query but it gives only
Black bean sauce
Black bean chicken
code i tried:
List<WebElement> folder = driver.findElements(By.xpath("//tr/td[#class='name']/a"));
for (WebElement webElement : folder) {
String foodName = webElement.getText();
System.out.println("text======" + foodName);
}
Use pipe | to select more nodes:
//tr/td[#class='name']/a | //tr/td[#class='name']/span[#class='complete']
See XPath or operator for different nodes

Categories