Extract Text from Span Element via XPath [Selenium] - java

I have the following HTML:
<div class="a-row a-spacing-small a-size-small">
<div class="a-row">
<a class="a-link-normal a-declarative g-visible-js reviewStarsPopoverLink" href="#" data-action="a-popover" data-a-popover="{"closeButton":"false","url":"/gp/customer-reviews/widgets/average-customer-review/popover/ref=wl_it_o_cm_cr_acr_img_hz?ie=UTF8&a=B05555JQP&contextId=wishi&link=1&seeall=1","name":"review-hist-pop.B075555RJQP","max-width":"700","position":"triggerBottom","data":{"itemId":"I2555555554GT","isGridViewInnerPopover":""},"header":"","cache":"true"}">
<i id="review_stars_I2J55555554GT" class="a-icon a-icon-star a-star-4-5">
<span class="a-icon-alt">4.5 out of 5 stars</span>
</i>
<i class="a-icon a-icon-popover"/>
</a>
<a class="a-link-normal g-visible-no-js" href="/product-reviews/B075555JQP/ref=wl_it_o_cm_cr_acr_txt_hz?ie=UTF8&colid=2K4U5555551D&coliid=I2J5555555T&showViewpoints=1">
<span class="a-letter-space"/>
<a id="review_count_I2J55555555GT" class="a-link-normal" href="/product-reviews/B05555555P/ref=wl_it_o_cm_cr_acr_txt_hz?ie=UTF8&colid=255555555D&coliid=I2555555GT&showViewpoints=1">(68)</a>
</div>
<div class="a-row">
<div class="a-row a-size-small itemAvailability">
<div class="a-row itemUsedAndNew">
</div>
I'm trying to extract the value 4.5 out of 5 stars via one of the following XPath:
.//*[contains(#id,'review_stars')]/span[#class='a-icon-alt']
.//*[contains(#id,'review_stars')]
However, everything that I've tried so far has failed (returns empty String)
The funny thing is that all of these XPaths actually work in Firebug so I'm not sure why it isn't working in my program (I suspect it has something to do with the fact that the rating isn't actually visible in browser unless you hover over a specific element but I'm not sure if/why/how this would cause the above mentioned problem and how to fix it)
Thanks!

You failed to include the image between the anchor and span. The span is inside the image, not a sibling of the anchor.
try:
.//*[contains(#id,'review_stars')]/i/span[#class='a-icon-alt']

I will attempt to answer my own question although I do not entirely understand why my previous code isn't working. If someone could provide me with an in depth explanation I will accept their answer as the final answer.
For now this is what works for me:
Instead of calling element.getText(); call element.getAttribute("innerHTML");
This returns the correct result but I would like to understand why getText() does not work in this case. Again, if someone could provide an XPath that works or could provide explanation to all this I will accept it as the final answer.
Thanks

To extract the value 4.5 out of 5 stars through XPath you can use :
//a[#class='a-link-normal a-declarative g-visible-js reviewStarsPopoverLink']/i[starts-with(#id,'review_stars_') and #class='a-icon a-icon-star a-star-4-5']/span[#class='a-icon-alt']
Update :
As you mentioned This does not work either. I just tried it. you must have missed out a part from the xpath which I have provided. My Answer was a proven one. See the snapshot below :
Note : Though your question was related to xpath you have pulled out your answer with respect to getText() method and getAttribute("innerHTML") method. How ever my Answer will be working with both getText() and getAttribute("innerHTML") method.

Related

How do I click 1 of 2 links with same name, no id and same class. selenium java

I'm trying to get selenium to click the select button but I can't use by.linkText() because there are two buttons with the same name.
I'm using this xpath ".//*[contains(#id,'view-something_111111_2A22DF2_)']/div/a[text()='Select']"; to find the button but it can't find it.
I've also tried ".//*[contains(#id,'view-something_111111_2A22DF2_)']/div/a";.
I've looked over the Selenium documentation and can't seem to find a solution.
Here is the section of website code:
<div id="view-something_111111_2A22DF2_0" class="coverage-wrap collapse" aria-expanded="false" style="height: 30px;">...</div>
<div class="btn-raplace">
<a class="btn-beer" data-toggle="collapse" data-target="#view-effectData_111111_2A22DF2_0">Select</a>
for reference, the second Select button has this code:
<div id="view-something_111111_2A3B5DF2_0" class="coverage-wrap collapse" aria-expanded="false" style="height: 30px;">...</div>
<div class="btn-raplace">
<a class="btn-beer" data-toggle="collapse" data-target="#view-effectData_111111_2A3B5DF2_0">Select</a>
which is why I am using the id in my xpath.
Thanks.
You can try this XPATH :- //*[#class="btn-raplace"]/a[#class="btn-beer"][1] here [1] is postion of ur button. Which you want to click
I can see two mistakes in the Xpath you are using.
First Mistake:
.//*[contains(#id,'view-something_111111_2A22DF2_)'] is incorrect.You have placed the single quote at a wrong place. It should be
//div[contains(#id,'view-something_111111_2A22DF2')]
Second Mistake
The element div with the class="btn-raplace" is not the child of the above element. I can see in the HTML that the above element has the closing tags before this element.
Please replace your XPATH with:
//div[contains(#id,'view-something_111111_2A22DF2')]/following-sibling::div[1]/a
Here is the Answer to your Question:
Use this xpath:
//div[#class='btn-raplace']/a[#class='btn-beer']
Let me know if this Answers your Question.

Having problems determining xpath

This one has me stumped. Usually I will use the Firebug feature to obtain the xpath for me but this time it doesn't seem to be working.
We have a US and UK version of our website. Firebug's xpath works on the US version but not on the UK version. If I grab the xpath using Firebug it's the exact same xpath for both sites but it works on the US version of the site and fails on the UK version of the site.
Here is the HTML:
<a class="ng-scope" ng-click="flightSearch.sort.$select(featuredItinerary.sortOrder)" tooltip="">
<h3 class="ng-binding">Fastest</h3>
<div class="row sort-block-row">
<div class="col-xs-12">
<h2 class="ng-binding">$283</h2>
</div>
I want to capture the value of the $283. This value will change constantly.
Here is what Firebug is telling me the xpath value is:
//html/body/div[2]/main/div/ui-view/ui-view/section/div/div[2]/div/ul/li[2]/a/div/div[1]/h2
Anyone have a better xpath value I can try and hope it works for both sites?
Following xpath should be able to help fetching the required value:
//a/h3[text()='Fastest']/descendant::h2
Try any of these below xpath
Assuming You are going to access the Fastest price.
Explanation: Start your xpath with <h3> tag using text method to match text as Fastest. Then move ahead with <h2> tag using following keyword. Because your <h2> tag is consider price.
//h3[contains(text(), 'Fastest')]/following::h2
OR
Explanation: Use class attribute of <div> tag. Then move ahead with <h2> tag. Because your tag is consider price.
//div[#class='col-xs-12']/h2

Having trouble locating text within span tags

I'm specifically searching for "Leg 0" and the other text below it like BOS and MAD, etc. I've played around with xpath and I seem to find text above this section and text below it but I can never find the "Leg 0" text and that below no matter what I do. I've been trying all morning to figure this out and no dice.
Here is the HTML.
<div>
<span class="debug-section ng-binding">Leg 0</span>
<span class="debug-value ng-binding">BOS</span>
-
<span class="debug-value ng-binding">MAD</span>
<span class="debug-value ng-binding">BACAT</span>
/
<span class="debug-value ng-binding">BA</span>
<span class="debug-value ng-scope" ng-if="!leg.excludeDynamic">Dynamic</span>
</div>
Any help is appreciated here, I am beyond frustrated.
First of all, provide some info about your code and exception you get as #Anderrson suggested.
And second, you can't find element based on text within span tags (innerHTML) using cssSelector, you should use xpath in that case. Or some javascript or jquery, but that would probably be overkill in this case.
The answer my friend is blowing in the wind. Brought up Firefox. Enabled the Firebug plug-in. Click the inspection tool. It highlights the HTML line you click on on the web page. Right click. Choose the Xpath copy to clipboard option.
Walla.

element.getText() method is not working in java selenium

<span class="label label-danger" style="font-size : 13px; font-weight : 400;">Critical</span>
Below is the xpath which I am using:
.//tr[#data-index='0']/td/span
I have a line in HTML source like above. So, I have used corresponding Xpath and used getText() method to get the text i.e. Critical. I am succeed in that.
But, I have another line in another page like this.
<div class="col-xs-12">
<div id="project-update-success-information" class="panel-confirmation success" style="display: none;">
<span class="fa fa-check"/>
Project Updated
</div>
Below is the xpath which I am using:-
.//*[#id='project-update-success-information']/span
I have used the corresponding Xpath and getText(),but unfortunately it doesn't retrieve the text for me. I doubted that there is no </span> close tag in the second line which causes the problem. Is there any other way to get the text?
This question has many answers already, but none of them really explains the problem. First, let us get your initial confusion about self-closing elements out of the way, before moving on to the real problem: No, it is not a problem that an element like
<span class="fa fa-check"/>
does not have a </span> tag. There is no need to indicate where it ends because the /> already tells you that this element does not contain anything and closes at this point.
Then let's look at only the fragment of the document that you show:
<div class="col-xs-12">
<div id="project-update-success-information" class="panel-confirmation success" style="display: none;">
<span class="fa fa-check"/>
Project Updated
</div>
</div>
An XPath expression like (note that most likely you do not need the . at the very beginning of the expression):
//*[#id='project-update-success-information']
will return the inner div element with all that it contains. What it does contain is, exactly in this order:
a whitespace-only text node
a self-closing span element with no content other than an attribute
the text node that contains "Project Updated"
So, it is not at all surprising that when you select the inner div and use .getText(), you end up with 2 text nodes in the result. Another way to get at the text content of an element is by using text() in the XPath expression:
//*[#id='project-update-success-information']/text()
which will return (individual elements separated by --------):
[whitespace-only text node]
-----------------------
Project Updated
The solutions are either
use getText() to retrieve all text nodes and later exclude those that only contain whitespace or
use an XPath expression that targets text nodes directly and excludes the ones that only contain whitespace. The standard way of doing this is with [normalize-space()]:
//*[#id='project-update-success-information']/text()[normalize-space()]
Note that, in general, there is no guarantee that the text content of an element will be in one single text node. It is very likely that you will sometimes encounter HTML or XML where elements have several text nodes, all of them containing non-whitespace characters, e.g.:
<div>
Project
<span/>
Updated
</div>
Try this text() method like below:-
//span[#class='fa fa-check']/text()
Hope it will help you :)
The element is empty and thus contains no text
<span class="fa fa-check"/>
If on the other hand it was like
<span class="fa fa-check">Some content</span>
then it would, as in yor first attempt, contain some text.
Without knowing more of the content I would try another xpath method: following-sibling.
Try:
driver.findElement(By.className("panel-confirmation success")).getText();

How to check for second element with class name and click it if it exists in Selenium Java

So I am writing automation tests using selenium and I am having a lot of trouble selecting the second element in a list of divs with the same class names
Boolean isExists2Accounts = driver.findElements(By.xpath("(//div[contains(#class, 'item-name')])[2]")).size() < 0;
if(isExists2Accounts)
{
//Finds second div element that has classname of item-name and clicks on it
driver.findElement(By.xpath("(//div[contains(#class, 'item-name')])[2]")).click();
}
else
{
driver.get("javascript:alert('There isn't a second account or you don't know how to select it!');");
Thread.sleep(5000);
org.testng.Assert.fail("transferTest6() Failed due to There isn't a second account or you don't know how to select it!");
}
HTML structure looks like this:
<div class="item-list">
<div class="item-name">
<div> clickable area </div>
<div class="button-wrap"></div>
</div>
<div class="item-name">
<div> clickable area </div>
<div class="button-wrap"></div>
</div>
<div class="item-name">
<div> clickable area</div>
<div class="button-wrap"></div>
</div>
<div class="item-name">
<div> clickable area </div>
<div class="button-wrap"></div>
</div>
</div>
Not really sure what I am doing wrong here, I looked at the html and there are 5 divs with the specified class name. Very new to selenium in general, using eclipse/junit/webdriver.
I have seen several questions similiar to this, and trying solutions people have posted have not worked. I have seen some suggestions to use .get(2) and I will try and implement that in the mean time.
Any help you could give would be good.
get(2) is THIRD element, not the second, as the countage begins from 0.
So:
driver.findElements(By.cssSelector(".item-name")).get(1).click();
OR depending on where is yr clickable
driver.findElements(By.cssSelector(".item-name div:not(.button-wrap)")).get(1).click();
Hey all the answer that was given by Stanjer works, I tested it with different markup, the developer that built the system I am testing through a random mousedown event (not click) for the html I am trying to interact with which was causing the problem.
So final solution with problem if it was a click event would be:
driver.findElements(By.cssSelector(".item-name")).get(1).click();
Just like he said.
However in this case I am instead going to send Javascript to the console to work with functions that have already been created by the developer.

Categories