How to find the respective element using xpath contains() function -selenium webdriver - java

This is the html snippet
<div class="ext-cal-wk-ct">
<table>
<tbody>
<tr>
<td><div>13</div></td>
<td><div>14</div></td>
<td><div>15</div></td>
<tr>
<tr>
<td><div>Calender note WebElement[no 13]</div></td>
<td><div>Calender note WebElement[no 14]</div></td>
<td><div>Calender note WebElement[no 15]</div></td>
</tr>
</tbody>
</table>
</div>
I want to find the respective element using xpath by the element no
for example:
if I use contains(text(),'13')--> WebElement no 13 should be returned
for contains(text(),'14')--> WebElement no 14 should be returned and so on
I have used two xpaths to find the elements individually but don't know how to connect them
//div[#class='ext-cal-wk-ct']/table[2]/tbody/tr/td/div[contains(text(),'13')]
//div[#class='ext-cal-wk-ct']/table[2]/tbody/tr/td/div[contains(text(),'Tim Cook')]
need some help on this
I want a xpath where I will pass the date and it will return me the calender note for that particular date

basically, contains is for partial matching.
When you write
contains(text(),'13')
there are 2 matching nodes,
<div>13</div>
and
<div>WebElement no 13</div>
so I would suggest to use :
//div[#class='ext-cal-wk-ct']/table[2]/tbody/tr/td/div[text(),'13']
to locate
<div>13</div>
or
//div[#class='ext-cal-wk-ct']/table[2]/tbody/tr/td/div[text()='WebElement no 13']
to locate this :
<div>WebElement no 13</div>

You can use below syntax by using contains in xpath
//tagname[contains(text(),'textname')]
I guess in your case you should consider exact match :
<td><div>15</div></td> : for this element
xpath => //td/div[text()='13']
and for this element : <td><div>WebElement no 13</div></td>
xpath => //td/div[text()='WebElement no 13']
i hope there is unique text in dom for given html snippet.

Related

How to extract the dynamic values of the id attributes of the table elements using Selenium and Java

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);

How to access nowrap element in selenium

I'm trying to access the first input field from the below HTML, but unable to access the field. Find the HTML details as below:
<tr>
<td>....</td>
<td nowrap>
<input type="text" name="details" id="details" value size="10" onfocus="doFieldFocusEvent(event)">
<input type="hidden" id=details1 value>
</td>
I have tried with the below approach but all returns false.
driver.findElement(By.xpath("//input[#id='details']"));
driver.findElement(By.xpath("//input[#name='details']"));
driver.findElement(By.id("details"));
driver.findElement(By.name("details"));
Can anyone help me to come out from this. Also can anyone give me idea on nowrap value.
I think a lot of relevant information got trimmed while you modified the actual HTML to present the the dummy HTML within the question. However a quick look at the attribute onfocus="doFieldFocusEvent(event)" confirms that the HTML DOM contains Javascript / Ajax Calls.
HTML nowrap Attribute
HTML nowrap Attribute attribute is a boolean attribute and when present it specifies that the content within the <td> cell should not wrap.
In the snapshot below the <td> element with nowrap attribute doesn't gets wrapped up while the <td> element without nowrap attribute gets wrapped up in absence of proper width/space.
Main Issue
I suspect your main issue is purely synchronization issue for which you have to induce WebDriverWait.
Solution
While you lookout for this particular <td> element induce WebDriverwait in-conjunction with ExpectedConditions clause as elementToBeClickable as follows :
WebElement elem = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[#id='details']")));

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

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

Selenium Xpath to find a table cells inside a div tag

I have the following HTML code that I need to check if text exists within a table cell:
<div class="background-ljus" id="AutoText">
<table class="topAlignedCellContent">
<tbody>
<tr>
<td>X1</td>
</tr>
<tr>
<td>X2</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td>Y1</td>
<td>Y2</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td>Z1</td>
<td>Z2</td>
</tr>
</tbody>
</table>
</div>
I have solved it like this:
By locator = getLocator(CommonConst.XPATH, "*//div[#" + type + "='" + anyName + "']");
fluentWait(locator);
WebElement div = getDriver().findElement(locator);
List<WebElement> cells = div.findElements(By.tagName("td"));
for (WebElement cell : cells) {
if (cell.getText().contains(cellText)) {
foundit = true;
}
}
But i think its a bit slow because I need to do this several times.
I tried to do this with only XPath but had no luck.
"*//div[#id='AutoText']//td[contains[Text(), 'celltext']]"
"*//div[#id='AutoText']//table//tbody//tr[td//Text()[contains[., 'celltext']]"
Anyone have a suggestion about why my XPath isn't working?
Wrong:
*//div[#id='AutoText']//td[contains[Text(), 'celltext']]
*//div[#id='AutoText']//table//tbody//tr[td//Text()[contains[., 'celltext']]
Correct (with shorter alternatives):
//div[#id='AutoText']//td[contains(text(), 'celltext')]
//div[#id='AutoText']//td[contains(., 'celltext')]
//div[#id='AutoText']/table/tbody/tr[td//text()[contains(., 'celltext')]
//div[#id='AutoText']/table/tbody/tr[td[contains(., 'celltext')]]
contains() is a function
text() needs to be lowercase
predicates can be nested
don't use // when you don't have to
Note
. refers to "this node" and, when given as an argument to a string function such as contains(), is the equivalent of string(.). This, however, is not at all the same as text().
string(.) creates the concatenation of all text nodes inside the current node, no matter how deeply nested. text() is a node test and by default selects only the direct children.
In other words, if the current node was <td>foo <b>bar</b> baz</td>, contains(text(), 'bar') would actually be false. (So would contains(text(), 'baz'), for a different reason.)
contains(., 'bar') on the other hand would return true, so would contains(., 'baz').
Only when the current node contains nothing but a single text node, text() and . are equivalent. Most of the time, you will want to work with . instead of text(). Set up your predicates accordingly.
You can do it with dynamic xpath as well
//div[#id='AutoText']/table[1]//tbody/tr[1]/td
Now just replace 1 with i and use for loop to see if the element return any value or not
Your xpath's are wrong. You should be using text() instead of Text(). Also contains() is a function with round braces and not square braces. Try this -
"//div[#id='AutoText']//td[contains(text(), 'celltext')]"
"//div[#id='AutoText']//td[contains(., 'celltext')]"
Or instead if you want all the child elements with the text to be displayed then use . instead of text()
Hope it helps.

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.
/<(.*?)[^>]*>(.*?)<\/(.*?)>/

Categories