I need to select testdt4 from the table. I am not able to get the whole list of the table items displayed as web elements. Like testdt4, there are many rows of the table which i need to find. Can I get the whole list in List<WebElement>? Please help.
<tr class="ng-scope" ng-class="::{warning: !$$cancelLastAction && (entity.$$inProgress || entity.$$hasError)}" ng-repeat="entity in locals.data">
<td class="selectRow">
<!-- ngRepeat: columnDef in locals.gridOptions.columnDefs -->
<td class="ng-scope" ng-repeat="columnDef in locals.gridOptions.columnDefs">
<ci-resource-grid-cell text-limit="textLimit" column="columnDef" data="entity">
<a class="ng-scope" ng-click="openLink(entity)" href="">
<div class="ciTruncate" truncate-limit="150" ci-truncate="columnDef.$$parse(entity)">
<span class="ng-scope">**testdt4**</span>
</div>
</a>
</ci-resource-grid-cell>
</td>
<!-- end ngRepeat: columnDef in locals.gridOptions.columnDefs -->
<td class="ng-scope" ng-repeat="columnDef in locals.gridOptions.columnDefs">
First - you need a established goal as to what you are trying to find. Are looking for all elements or Single element. If multiple elements.
[https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/SearchContext.html#findElements-org.openqa.selenium.By-]
are you trying to find Cells or Rows or whole table? Cell tag - td/Row - tr/Table - table.
with find elements, xpath search with following will give you all cells:
Xpath Expression::
"//td//span[contains(#class,"ng-scope") and contains(text(),"testdt4")]"
Where I gave //tr above, replace with table or tr as needed [pt2]
Example:
Xpath Expression::
"//tr//span[contains(#class,"ng-scope") and contains(text(),"testdt4")]"
Xpath Expression::
"//table//span[contains(#class,"ng-scope") and contains(text(),"testdt4")]"
List someList = driver.findElement(By.xpath("Xpath Expression"))
Show me your code i will modify it:: Update You should be using TD for cells.
By identifierXPath = By.xpath("//tr//span[contains(#class,'ng-scope') and contains(text(),'testdt4')]");
List<WebElement> list_Cells = driver.findElements(identifierXPath);
System.out.println(list_Cells.size());
for (WebElement single_Cell : list_Cells){
System.out.println("Cell Text ::-" + single_Cell.getText().trim());
}
Related
I have a table where each row will have a download link with a (partly) auto-generated id element. The reason for this is that the actual href-element will allways be "#", so the id's separate the downloads.
I need to find the name of that id element in the td. That is: I know the table row has an id element, and I know part of the name, and I need to get the exact name.
I'm accessing each row one at a time, so I only need to look within ONE td at a time. No need to look through the whole table.
I know well how to find an element when I know the name. But to find the element when I only know the type is another thing.
...
<tr>
<td class="journalTable-journalPost"
<a class="htext-small" href="#" id="downloadJournalPost-345">Download</a>
</td>
</tr>
<tr>
<td class="journalTable-journalPost"
<a class="htext-small" href="#" id="downloadJournalPost-346">Download</a>
</td>
</tr>
...
I cannot find any method(s) in the webdriver that lets me find an element by type.
Partial name would work, since the id's get the name "downloadJournalPost-xxx", where only xxx changes. But link text is the only value I can find which lets me search for a partial match.
EDIT: More complete markup.
<td class="journalTable-journalpost">
<span class="hb-tekst--sekundar">In <!----><est-ikon class="ng-star-inserted">
<div aria-hidden="true" class="hb-ikon hb-ikon--pil3-inn ">
<svg focusable="false">
<use xlink:href="#ikon-pil3-inn"></use>
</svg>
</div></est-ikon><!----></span>
<span class="hb-tekst--mellomTittel hb-avstandIngen"> Application and attachments</span>
<a class="hb-tekst--liten" href="#" id="lastNedJournalPost-2892">Download journal post</a>
</td>
Until you find the element first, you can't retrieve the attribute values of it.
Use findElements method to fetch all links using the following locator
table tr td[class='journalTable-journalPost'] a
Then iterate through each element using for-each to fetch id for each element.
Sample code:
List<WebElement> listOfLinks = driver.findElements(By.cssSelector("table tr td[class='journalTable-journalPost'] a"));
for(WebElement link: listOfLinks) {
System.out.println("id:" + link.getAttribute("id"));
}
To print the List of id attribute of the element you need to induce WebDriverWait for the visibilityOfAllElementsLocatedBy() and you can use Java8 stream() and map() and you can use either of the following Locator Strategies:
cssSelector:
List<String> myID = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("td.journalTable-journalPost>a.htext-small"))).stream().map(element->element.getAttribute("id")).collect(Collectors.toList());
System.out.println(myIDs);
xpath:
List<String> myIDs = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//td[#class='journalTable-journalPost']/a[#class='htext-small' and text()='Download']"))).stream().map(element->element.getAttribute("id")).collect(Collectors.toList());
System.out.println(myIDs);
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
How would I be able to use JSoup to get the data-code value from a table row?
Here is what I have tried but it just prints nothing:
Document doc = Jsoup.connect("http://www.example.com").get();
Elements dataCodes = doc.select("table[class=team-list]");
for (Element dataCode : dataCodes)
{
System.out.println(dataCode.attr("data-code"));
}
The HTML code looks like this:
<body>
<div id-=""main">
<div id="inner">
<div id="table" class="scores-table">
<table class ="team-list">
<tbody>
<tr data-code="1" class="data odd"></tr>
<tr data-code="2" class="data even"></tr>
<tr data-code="3" class="data odd"></tr>
<tr data-code="1" class="data even"></tr>
</tbody>
</table>
</div>
</div>
</div>
I want it to print out the data-code value on each row of the table (which is the team number).
Your selector should go down to tr elements:
Elements dataCodes = doc.select("table.team-list tr");
According to the comments, this still results into an empty list - in this case, the table is probably dynamically generated with the help of javascript logic or a separate AJAX request.
In this case, one of the possible approaches would be to have a real browser handle that dynamic javascript, AJAX part. Try selenium browser automation framework:
WebDriver driver = new FirefoxDriver();
driver.get("http://www.example.com");
List<WebElement> elements = driver.findElements(By.cssSelector("table.team-list tr"));
for(WebElement element: elements)
{
System.out.println(element.getAttribute('data-code'));
}
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.
/<(.*?)[^>]*>(.*?)<\/(.*?)>/
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());
}