I have below html,
<!DOCTYPE html>
<html>
<body>
<table border="1">
<tr>
<th>Month</th>
<th>Savings</th>
<th>Savings for holiday!</th>
</tr>
<tr>
<td>January</td>
<td>$100</td>
<td rowspan="2">$50</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
</tr>
</table>
</body>
</html>
I want to generate below html using jsoup,
<tr>
<th>Month</th>
<th>Savings</th>
<th>Savings for holiday!</th>
</tr>
<tr>
<td>January</td>
<td>$100</td>
<td rowspan="2">$50</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
<td>$50</td>
</tr>
I have currenty written this piece of code through which i can get the rowspan cell and its associated td index
final Elements rows = table.select("tr");
int rowspanCount=0;
String rowspanString ="";
for(Element row : rows){
int rowspanIndex = 0;
for(Element cell: row.select("td")){
rowspanIndex++;
if(cell.hasAttr("rowspan")){
rowspanCount = Integer.parseInt(cell.attr("rowspan"));
rowspanString = cell.ownText();
cell.removeAttr("rowspan");
}
}
}
Possible HINT: For condition,
cell.hasAttr("rowspan")
Get row-index, like;
int index = row.getIndex();
and then get next Row by index+1, like;
Element eRow = rows.get(index+1);
then append td-Element to this row, this would be your next row to rowspan-row.
After coding everything, I found the solution. Below is the code,
for (Element row : rows) {
int cellIndex = -1;
if(row.select("td").hasAttr("rowspan")){
for (Element cell : row.select("td")) {
cellIndex++;
if (cell.hasAttr("rowspan")) {
rowspanCount = Integer.parseInt(cell.attr("rowspan"));
cell.removeAttr("rowspan");
Element copyRow = row;
for (int i = rowspanCount; i > 1; i--) {
nextRow = copyRow.nextElementSibling();
Element cellCopy = cell.clone();
Element childTd = nextRow.child(cellIndex);
childTd.after(cellCopy);
}
}
}
}
}
It duplicates the rowspan cell to all the following rows that should contain it. As well removes the attribute rowspan for removing any further discrepancy.
You can append this row simply with this code:
Elements rows = table.select("tr > td[rowspan=2]");
for (Element row : rows) {
row.parent().nextElementSibling().append("<td>$50</td>");
}
Related
From the below html i want to check each row in the table header value and if matched need retrieve the td value
below is my html
<table class="span-5" id="summaryTable" title="Table showing Summary data">
<tbody>
<tr>
<th class="width-40" id="num">
(12) App no:
</th>
<td headers="num">
(11)
<strong>2796179</strong>
</td>
</tr>
<tr>
<th class="noLines alignLeft width35" id="EnglishTitle">
(54) English Title:
</th>
<td class="noLines alignLeft width65" headers="EnglishTitle">
FRAME BIT-SIZE ALLOCATION
</td>
</tr>
<tr>
</tbody>
</table>
i want to collect the each th tag value (i.e (12) App no (54) English Title)
my java code
WebElement summary = driver.findElement(By.xpath("//*[#id='summaryTable']/tbody"));
List<WebElement>rows = summary.findElements(By.tagName("tr"));
for (int i=1;i<=rows.size();i++){
String dc = driver.findElement(By.xpath("//*[#id='summaryTable']/tbody/tr["+i+"]/td/th/a")).getText();
if (dc.equalsIgnoreCase("(12) App no")){
appNo = driver.findElement(By.xpath("//*[#id='summaryTable']/tbody/tr["+i+"]/td/strong")).getText();
}
}
but i'm getting no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id='summaryTable']/tbody/tr[1]/td/th/a"}
Please use the below code for this
WebElement elem = driver.findElement(By.id("summaryTable"));
List<WebElement> lists = elem.findElements(By.tagName("th"));
for(WebElement el : lists){
WebElement element = el.findElement(By.tagName("a"));
String str = element.getAttribute("innerHTML");
System.out.println(str);
}
I think you are making it a bit complicated, can you try bit simpler version?
public String getRequiredDataFromTableFromRow(String header){
WebElement table = driver.findElement(By.id("summaryTable"));
List<WebElement> rows = table.findElements(By.tagName("tr"));
for (WebElement row:rows) {
if(row.getText().contains(header)){
return row.findElement(By.tagName("td")).getText();
}
}
return null;
}
Cells are also arrays within the row, so you need to specify the position to get the text. The th tag is not there within the td tag.
Try the following code:
WebElement summary = driver.findElement(By.xpath("//*[#id='summaryTable']/tbody"));
List<WebElement>rows = summary.findElements(By.tagName("tr"));
for(int i = 1; i <= rows.size(); i++) {
String dc = driver.findElement(By.xpath("//*[#id='summaryTable']/tbody/tr[" + i + "]/th[0]")).getText();
if(dc.equalsIgnoreCase("(12) App no")) {
appNo = driver.findElement(By.xpath("//*[#id='summaryTable']/tbody/tr[" + i + "]/td[0]")).getText();
}
}
Below is basically for getting you the text for each "th" element.
WebElement summary = driver.findElement(By.id("summaryTable"));
List<WebElement>rows = summary.findElements(By.tagName("th"));
for(WebElement row : rows){
row.getText();
}}
In the above code, I am getting the reference using the "id" and using same object reference in order to get the elements list for "th" tag.
In case you want to perform operation on the text been found can be done using the reference of the row element
I want to target specific td inside a tr.
This is my code:
private void fletch(String name) throws IOException, JSONException {
final String iron = "img=2";
final String ui = "img=3";
final String hc = "img=10";
String url = "services.runescape.com/m=hiscore_oldschool/hiscorepersonal.ws?user1=";
if ( name.toLowerCase().indexOf(iron.toLowerCase()) != -1 ) {
url = "http://services.runescape.com/m=hiscore_oldschool_ironman/hiscorepersonal.ws?user1=";
}else if( name.toLowerCase().indexOf(ui.toLowerCase()) != -1 ){
url = "http://services.runescape.com/m=hiscore_oldschool_ultimate/hiscorepersonal.ws?user1=";
}else if( name.toLowerCase().indexOf(hc.toLowerCase()) != -1 ){
url = "http://services.runescape.com/m=hiscore_oldschool_hardcore_ironman/hiscorepersonal.ws?user1=";
}
String[] parts = name.split(">");
String part2 = parts[1];
String fin = part2.replaceAll("\\s","+");
url+=fin;
Document doc = Jsoup.connect(url)
.data("query", "Java")
.userAgent("Mozilla")
.cookie("auth", "token")
.timeout(3000)
.post();
//core part
Element table1 = doc.select("table").first();
String body = table1.toString();
Document docb = Jsoup.parseBodyFragment(body);
Element bbd = docb.body();
String hhk = bbd.toString();
//This is where i dont know how to target the td data.. Tried this (cant check code so came on here):
String overall = bbd.getElementsByTag("td").get(4).text();
Now this gives me this HTML code:
<table cellpadding="3" cellspacing="0" border=0 style="max-width: 355px;">
<tr><td colspan="5" align="center"><b>Personal scores for big kurwaaa</b></td></tr>
<tr>
<td colspan="2" style="text-align:left;padding-left:24px;"><b>Skill</b></td><td align="right"><b>Rank</b></td><td align="right"><b>Level</b></td><td align="right"><b>XP</b></td>
</tr>
<tr><td width="35"></td><td width="100"></td><td width="75"></td><td width="40"></td><td width="75"></td></tr>
<tr>
<td></td>
<td align="left"><a href="overall.ws?table=0&user=big+kurwaaa">
Overall
</a></td>
<td align="right">7,430</td>
<td align="right">466</td>
<td align="right">6,164,312</td>
</tr>
<tr>
<td align="right"><img class="miniimg" src="http://www.runescape.com/img/rsp777/hiscores/skill_icon_attack1.gif"></td>
<td align="left"><a href="overall.ws?table=1&user=big+kurwaaa">
Attack
</a></td>
<td align="right">14,475</td>
<td align="right">19</td>
<td align="right">4,304</td>
</tr>
I want to target the 3 td with data inside every tr. So for example:
<td align="right">7,430</td>
<td align="right">466</td>
<td align="right">6,164,312</td>
and so on from the "overall" tr to the last. Is there any way to do in a simple way that will give me the option to loop through the data and create a JSON/map?
Ps: new to java
If you want to get all the tr tags inside bbd use getElementsByTag.
It will return Elements, by which you can browse through all the tr tags by index (0 based index).If want to skip first 3 tr tags just start loop from index : 3, and so for td tags
Here is the demo code :
Elements trList = bbd.getElementsByTag("tr");
for (int i = 3; i < trList.size(); i++) {
System.out.println("----------------- TR START -----------------");
Elements tdList = trList.get(i).getElementsByTag("td");
for (int j = 2; j < tdList.size(); j++) {
System.out.println(tdList.get(j));
}
System.out.println("------------------ TR END ------------------");
}
String url = "yourUrl";
Document doc = Jsoup.connect(url).get();
Element table = doc.select("table[class=tableClass]").first();
Iterator<Element> iterator = table.select("td[align=right]").iterator();
iterator.next();//skip first
iterator.next();//skip second
System.out.println(iterator.next().text());
i have write the below code for find the particular column value in web table, but if i give the static value in row and column value , driver is identifying the value , but if i get the value through for loop, i am not able to retrieve the values.
WebElement tabledata = driver.findElement(By.id("divAttendanceDetails"));
List<WebElement> Rows = tabledata.findElements(By.xpath("//*[#id='divAttendanceDetails']/table[1]/tbody/tr"));
System.out.println("NoofRowsinthetable" + Rows.size());
String identifyvalue = "Leave Applied";
int leavecount = 0;
for (int getrowvalue=0; getrowvalue < Rows.size()-1;getrowvalue++)
{
List<WebElement> Columns = Rows.get(getrowvalue).findElements(By.xpath("//*[#id='divAttendanceDetails']/table[1]/tbody/tr/td"));
System.out.println("NoofColumnsinthetable" + Columns.size() );
for (int getcolumnvalue =0;getcolumnvalue<Columns.size(); getcolumnvalue++ )
{
String cellvaues = driver.findElement(By.xpath("//*[#id='divAttendanceDetails']/table[1]/tbody/tr["+getrowvalue+"]/td["+getcolumnvalue+"]")).getText();
System.out.println(cellvaues);
if(identifyvalue.equalsIgnoreCase(cellvaues))
{
leavecount = leavecount+1;
System.out.println("Leavecounttilldate" + leavecount );
}
}
}
Please help to resolve the issue
Html Page looks
<div id="newdiv"><table class="ariel" cellspacing="0" cellpadding="3" rules="all" border="1" id="dgResults" style="width:100%;border-collapse:collapse;">
<tbody><tr class="bluerow" align="left" style="font-weight:bold;">
<td style="width:15%;">start Date</td><td style="width:15%;">end Date</td><td style="width:15%;">in Time</td><td style="width:15%;">Out Time</td><td style="width:15%;">totalhours Office</td><td style="width:20%;">Details</td>
</tr><tr class="row2" align="left">
<td>01/01/2015</td><td>01/01/2015</td><td>00:00</td><td>00:00</td><td>00:00</td><td align="left">Holiday</td>
</tr><tr class="row2" align="left">
<td>01/02/2015</td><td>01/02/2015</td><td>00:00</td><td>00:00</td><td>00:00</td><td align="left">Leave Applied</td>
</tr><tr class="row2" align="left">
<td>01/03/2015</td><td>01/03/2015</td><td>00:00</td><td>00:00</td><td>00:00</td><td align="left">Weekend</td>
</tr><tr class="row2" align="left">
<td>01/04/2015</td><td>01/04/2015</td><td>00:00</td><td>00:00</td><td>00:00</td><td align="left">Weekend</td>
</tr><tr class="row2" align="left">
<td>01/05/2015</td><td>01/05/2015</td><td>13:02</td><td>19:01</td><td>04:38</td><td align="left"> </td>
</tr>
</tbody></table></div>
I have faced similar issue and have resolved by using String.format().
String xpath = "//*[#id='divAttendanceDetails']/table[1]/tbody/tr[%s]/td[%s]";
String cellvaues = driver.findElement(By.xpath(String.format(xpath, getrowvalue, getcolumnvalue))).getText();
one issue with yours xpath is its indexes. Xpath indexes starts with 1.
ref: Why do indexes in XPath start with 1 and not 0?
but this can be issue if you have only one row, results for other rows should be displayed.
It will be helpful if you share the HTML and your current output.
Followed the html you have provided. It does not necessarily matches the code you have in original post.
List<WebElement> Rows = driver.findElements(By.cssSelector("#dgResults tr"));
System.out.println("NoofRowsinthetable" + Rows.size());
for (int i = 0; i < Rows.size(); i++)
{
//find the columns in specific row
List<WebElement> Columns = Rows.get(i).findElements(By.cssSelector("td"));
System.out.println("NoofColumnsinthetable" + Columns.size() );
for (int j = 0; j < Columns.size(); j++ )
{
String text = Columns.get(j).getText();
System.out.println(text);
/* adjust as you needed.
if(identifyvalue.equalsIgnoreCase(text))
{
leavecount = leavecount+1;
System.out.println("Leavecounttilldate" + leavecount );
}
*/
}
}
Note: I didn't test the code on my end. May have some syntax issue
I have a table with the following html:
<TABLE class=data-table cellSpacing=0 cellPadding=0>
<TBODY>
<TR>
<TD colSpan=4><A id=accounting name=accounting></A>
<H3>Accounting</H3></TD></TR>
<TR>
<TH class=data-tablehd align=left>FORM NO.</TH>
<TH class=data-tablehd align=left>TITLE</TH>
<TH class=data-tablehd align=right>Microsoft</TH>
<TH class=data-tablehd align=right>Acrobat</TH></TR>
<TR>
<TD><A id=1008ft name=1008ft>SF 1008-FT</A></TD>
<TD>Work for Others Funding Transfer Between Projects for an Agreement</TD>
<TD align=right><A
href="https://someurl1"
target=top>MS Word</A></TD>
<TD align=right><A
href="https://someurl2"
target=top>PDF </A></TD></TR>
...
I need to parse the <TR> data getting something like
SF 1008-FT, Work for Others ... an Agreement, https://someurl1, https://someurl2
I have tried using the following code:
URL formURL = new URL("http://urlToParse");
Document doc = Jsoup.parse(formURL, 3000);
Element table = doc.select("TABLE[class = data-table]").first();
Iterator<Element> ite = table.select("td[colSpan=4]").iterator();
while(ite.next() != null) {
System.out.println(ite.next().text());
}
However this only returns the "back to Top" and some different headings located throughout the table.
Can someone help me write the correct JSoup code to parse the information I need?
I have not time to test, but you can use something like this:
Element table = doc.select("TABLE[class = data-table]").first();
Elements rows = table.select("tr");
for (Element td: rows.get(2).children()) {
System.out.println(td.text());
}
You get the children of the 3rd row of the table.
I found the solution with some small modification to a similar thread. The code that provides the solution is given below:
for (Element table : doc.select("table")) {
for (Element row : table.select("tr")) {
Elements tds = row.select("td");
formNumber = tds.get(0).text();
title = tds.get(1).text();
link1 = tds.get(2).select("a[href]").attr("href");
link2 = tds.get(3).select("a[href]").attr("href");
}
}
I have a table that is populated depending on how many cars are there. If the number of cars is 1 it will give me the 1 row (where 5 attributes are arranged in 5 columns). If the number of cars is 2 it will give me 2 rows(same 5 attributes), & so on. Now I need to split the table into as many cars are there so that there is just one row for every car. I need to do it in JSP and trying to use the tag <c:choose> or <c:if>, but isn't working . Please help
You need <c:forEach> here. With it you can iterate over any List<T> and print the <tr> on every iteration. Assuming that you have populated a List<Car> and put it in the EL scope as ${cars}, here's an example:
<table>
<c:forEach items="${cars}" var="car">
<tr>
<td>${car.make}</td>
<td>${car.model}</td>
<td>${car.type}</td>
<td>${car.color}</td>
<td>${car.price}</td>
</tr>
</c:forEach>
</table>
See also:
Beginning and intermediate JSP/Servlet tutorials
Hidden features of JSP/Servlet
<html>
<head>
<title>Sample code - Traversing an HTML Table with JavaScript and DOM Interfaces</title>
<script>
function start() {
// get the reference for the body
var body = document.getElementsByTagName("body")[0];
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table");
var tblBody = document.createElement("tbody");
// creating all cells
for (var j = 0; j < 2; j++) {
// creates a table row
var row = document.createElement("tr");
for (var i = 0; i < 2; i++) {
// Create a <td> element and a text node, make the text
// node the contents of the <td>, and put the <td> at
// the end of the table row
var cell = document.createElement("td");
var cellText = document.createTextNode("cell is row "+j+", column "+i);
cell.appendChild(cellText);
row.appendChild(cell);
}
// add the row to the end of the table body
tblBody.appendChild(row);
}
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 2;
tbl.setAttribute("border", "2");
}
</script>
</head>
<body onload="start()">
</body>
</html>