Selenium, Java. Need to select ancestor element inside table by Xpath - java

I have an HTML page containing the following code :
<table class="report" style="width:100%">
<tbody>
<tr>
<th/>
<th>Position Open
<br>
<span class="timestamp">27/7/2016 16:12:12</span>
</br>
</th>
<th>Position closed
<br>
<span class="timestamp">27/7/2016 16:12:42</span>
</br>
</th>
</tr>
<tr>
<td>
<span dir="ltr">EURJPY</span>
</td>
<td>116.098</td>
<td>116.156</td>
</tr>
</tbody>
</table>
On this page I have another table with the same class attribute "report" but only this table contains texts "Position Open" and "Position Closed".
I need to select elements containing the "EURJPY", "116.098" and "116.156" data.
These elements content is changing i.e. instead of "EURJPY" may appear "EURUSD" or "GBPCAD" etc.
I tried the following code:
driver.findElement(By.xpath("//span[text()='Position Open']/ancestor::table[#class='report'](//tr)[2]/td/span")).getAttribute("textContent");
to get the first required field text but got the Invalid selector error.

Your XPath is close but there were a couple issues.
//span[text()='Position Open']/ancestor::table[#class='report'](//tr)[2]/td/span
You are searching for a SPAN that contains the text 'Position Open' when in fact it is a TH that contains the text.
//th[text()='Position Open']/ancestor::table[#class='report'](//tr)[2]/td/span
(//tr) should be corrected to //tr
//th[text()='Position Open']/ancestor::table[#class='report']//tr[2]/td/span
What you want is the text contained in the TD, not the SPAN. If you pull the text from the TD you can get the text you want from all three elements. If you pull the SPAN, then you will also need to pull the last two TDs. This way is just simpler.
...and finally, the TH contains more than just the text you are looking for. Use .contains() to get a match.
//th[text()='Position Open']/ancestor::table[#class='report']//tr[2]/td
So we take that XPath and put it into Java code and we get the below.
List<WebElement> tds = driver.findElements(By.xpath("//th[contains(text(),'Position Open')]/ancestor::table[#class='report']//tr[2]/td"));
for (WebElement td : tds)
{
System.out.println(td.getText());
}

There can be issues matching the text sometimes, use contains instead, try this selector
//th[contains(.,'Position')]/ancestor::table[#class='report']//tr[2]/td/span

You can use this xpath to locate the 3 <td> tags you are interest in
//th[contains(text(),'Position Open')]/ancestor::table//tr[2]/td
Using it will give you list of three elements, you can extract the text from them
List<WebElement> tds = driver.findElement(By.xpath"//th[contains(text(),'Position Open')]/ancestor::table//tr[2]/td");
String currency = tds.get(1).getText(); // this will be EURJPY
tds.get(2).getText(); // 116.098
tds.get(3).getText(); // 116.156

Related

How can I add hyperlinks to columns of a table using thymeleaf th:each?

I'm trying to create hyperlinks for each element in a table generated by thymeleaf.
<tbody>
<tr th:each="author :${authors}">
<td th:text="${author.id}"></td>
<a th:href="#{/authors/{id}(id=${author.id})}">
<td class="authorLink" th:text="${author.firstName}"></td>
</a>
<td th:text="${author.lastName}"></td>
</tr>
</tbody>
The code above is giving me an output of the generated hyperlinks outside of the table.
This is a link to the generated html.
https://i.gyazo.com/7dae68eb42cd084b59030e7b17590e5e.png
"linklinklinklink" is the output of the generated hyperlinks. I would like for the 'First Name' column to become hyperlinks.
If anyone can tell me how I can accomplish this that would be great.
Place your <a> tag inside the <td> cell where you want the link to appear:
<td>
<a th:href="#{/authors/{id}(id=${author.id})}"
th:text="${author.id}"></a>
</td>
Note how you can use a th:text="..." attribute inside the <a> tag, as well, to control the visible text for the link.
In your case, you had a <a> tag inside a row, but not part of any cell. This is invalid HTML, so your browser's HTML renderer dumped the links somewhere else (above the table, in this case).

How to get the xpath of a <b> tag which is designed below the div text

I would like to fetch a text content from a tag which is located just below a div text named ,'Authors:'.
I have identified the location for 'Authors' but I need to traverse through each block of authors and need to fetch the corresponding text associated with 'Authors' label.I have tried the following but I couldn't get the result.
//table[#id='thdListTable']//td[#class='msgHead']//div[contains(text(), 'Author:')]
//td[#class='msgHead']/div[contains(text(), 'Author:')]
<table id="thdListTable" width="95%">
<tbody>
<tr>
<td class="msgHead">
<div>
Author:
<b>Kurt Wendt <Kurt_Wendt (AT) globetax D.O.T com></b>
<br/>
Subject:
<b>To Impersonate on MS SQL</b>
-
<a target="_new" href="/archives/msg/501727">Link</a>
<br/>
Posted:
<b>2015-10-14 11:31:56</b>
<br/>
</div>
</td>
</tr>
//table[#id='thdListTable']//div/b[1]"
you can try to go for the first b element that is found below your div, because that should be the author's name, if I understood you correctly.
Then just get the text via getText() method
string xpathExpression = "//td[#class='msgHead']/div[contains(text(), 'Author:')]/b[1]";
string authorName = driver.findElement(By.xpath()).getText();
yes you can reach to there by using the code
//td[#class='msgHead']/div[contains(text(), 'Author:')]/b[1]
So you can retrieve the same results for others by changing the text contain name.

How can I get the last tag inner HTML?

I want to get the last item which the last item in the specific tags,
I mean ;
<tr>
<td><b>my name</b></td>
<td><spec id="nm" nm="eg">Example Name</spec>
</td>
</tr>
....
<tr>
<td><b>samp2</b></td>
<td title="samp2"><div>Example 2</div>
</td>
</tr>
I want to reach "Example Name" I want to write a dynamic program? How can I do that?
(you can see the the last tag is "spec" maybe the other scenerio the last tag is sam how can I find last tag inner html? second sample I want to get Example 2)
updated sample
if I has this :
<table>
<tr>
<td>1</td>
<td><div>2</div></td>
</tr>
<tr>
<td><span>3</span></td>
</tr>
</table>
So I need the output should be:
2 and 3
because they are the last tags inner html under tr tag.
(I want to last tag under tr tag , but if it has child element I want to its inner html)
thanks in advance?
You can use jsoup html parser to do it, you can use css or jquery like selector to find element
String html = "<table><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table>";
Document doc = Jsoup.parse(html);
System.out.println(doc);
Elements elements = doc.select("tr td:last-child");
for(Element element: elements) {
System.out.println(element.html());
}
output
2
4
you can try with a regex like :
/<spec[^>]*>(.*?)<\/spec>/
i think it is not efficient but you can try, check the regex for a better performance
/<td[^>]*>(.*?)<\/td><\/tr>/
this is an approximation. would fail the subject of child. You can use this result to remove span, div etc.
/<(.*?)[^>]*>(.*?)<\/(.*?)>/

Extracting text with jsoup out of a table with breaks

Some knows how I can extract those texts with Jsoup?
<TR>
<TD bgColor=#ffa55c><B>
The first text I want. </B><BR>
<BR>
The second text I want <BR>
</TD>
</TR>
I can get the first one with:
Element element = doc.select("tr td:eq(1) b").get(1);
element.text();
But I don't get the second one :(
You need to close your table cell tag TD to make the HTML well formed
<table>
<TR>
<TD bgColor=#ffa55c><B>
The first text I want. </B><BR>
<BR>
</TD><TD> <!-- add this -->
The second text I want <BR>
</TD>
</TR>
</table>
otherwise JSoup will consider the first & second cell as one and get will throw an IndexOutOfBoundsException, then you can simple use
Element element = doc.select("td").get(2);
Using the table data you gave us, you can easily get all the text in one fell swoop:
String html = "<TR><TD bgColor=#ffa55c><B>The first text I want.</B><BR><BR>The second text I want<BR></TD></TR>";
Document doc = Jsoup.parse(html);
System.out.println("test: " + doc.text());
With the output:
test: The first text I want. The second text I want
I think you need to restrict your select to the TR and ignore everything after it, so make it something like
// get the TRs
Elements elements = doc.select("tr");
// iterate through the TRs
for (Element element: elements){
System.out.println(element.text());
}

How to iterate over <td> tags with condition using jsoup

I am able get all text with in tags but I want to access only specific td tags.
Eg.I want to get data of second cell text whose first cell html contains attribute
a name="manufacturer"
or Content.I am using Jsoup.
<tabel>
<tr>
<td><a name="Manufacturer"></a>manufacturer</td>
<td>happiness</td>
</tr>
<td>manuf</td>
<td>hap</td>
</tr>
<tr>
<td>tents</td>
<td>acd</td>
</tr>
<tr>
<td><a name="Content"></a>Contents</td>
<td>abcd</td>
</tr>
</tabel>
I am using the code ..
doc.select("a[name=Manufacturer]");
..but its giving me the reference of cell one ,I need to go to cell two get cell two text
You need to use selector like [attr=value]: elements with attribute value, e.g. [width=500].
Take a look at official documentation Selector Syntax

Categories