Why does my XPath not select based on text()? - html

I have a page in firefox (no frame) which contains the following part of html code:
...
<div class="col-sm-6 align-right">
<a href="/efelg/download_zip" class="alert-link">
Download all results in .zip format
</a>
</div>
...
which I want to select with a selenium XPATH expression. In order to test my XPATH expression, I installed an add-on for firefox called 'TryXpath' in order to check my expression. However, the expression seems to be incorrect, as no element is selected. Here is the expression:
//a[text()= "Download all results in .zip format"]
but what is wrong with that expression? I found it in different SO answers - but for me this does not seem to work. Why do I get 0 hits? Why is the expression wrong find the html element I posted above (no frame, element is visible and clickable...)

You can try this:
//a[contains(text(),'Download all results in .zip format')]
it is working in my side, Please try at let me know

The reason your XPath isn't selecting the shown a element is due to the leading and trail white space surrounding your targeted text. While you could use contains() as the currently upvoted and selected answer does, be aware that it could also match when the targeted string is a substring of what's found in the HTML in an a element -- this may or may not be desirable.
Consider instead using normalized-space() and testing via equality:
//a[normalize-space()='Download all results in .zip format']
This will check that the (space-normalized) string value of a equals the given text.
See also
Testing text() nodes vs string values in XPath

Related

XPath containing 2 or more "OR" conditions not working?

There is an anchor tag, whose value can be changed by the user. Now, i want to write an Xpath query that searches for multiple link text names in one statement itself.
Signin
now, link text value can be changed by user profile. for eg, "Login", "Log-in", "Click here to login" or "Login now"
If i write xpath:-
//a[contains(text(),'Login') or contains(text(),'Log-in') or contains(text(),'Login now') or contains(text(),'click here to Login')]
Then it fails. I need to click this element using Selenium.
Please help.
Important notes:
Only use contains() when you need substring testing. See What does contains() do in XPath?
Understand string-values: See Testing text() nodes vs string values in XPath
Beware of whitespace variations. See What is the purpose of normalize-space()?
Your posted markup has Signin, but your XPath does not.
Mind case sensitivity: click here to Login is not the same as Click here to Login.
XPath 1.0
If you're certain there are no whitespace variations:
//a[.='Login' or .='Log-in' or .='Click here to login' or .='Login now']
Otherwise:
//a[ normalize-space()='Login"
or normalize-space()='Log-in'
or normalize-space()='Click here to login'
or normalize-space()='Login now']
XPath 2.0
//a[normalize-space()=('Login','Log-in','Click here to login','Login now')]
XPath is based on sequences. So you can use a comma separated list, i.e. sequence, to imitate logical OR conditions.
XPath
//a[text()=("Login","Log-in","Click here to login")]

Really struggling trying to separate strings within an element that are separated by a <br> [duplicate]

This question already has answers here:
XPath for text after <br/>
(3 answers)
Closed 5 years ago.
I am developing some automation tests using webdriver/node/protractor.
I am working with the following HTML:HTML
I cannot for the life of me figure out how to either A)identify only the value after the break (Pre-Tax) or define my data comparison xml to account for the break. Here is my xpath:
//td/span[contains(text(),'selectedBenefit')]/../../td[8]
I have no problem navigating to the specific text a couple of different ways (node(), text(), etc...) however when I run my test, I get an error saying I need to return an element and not text.
Error >
Failed: invalid selector: The result of the xpath expression "//td/span[contains(text(),'Telemedicine - Sequencing')]/../../td[8]/node()[3]" is: [object Text]. It should be an element.
**EDIT: This question has been marked as a duplicate, and I don't think it is, so I am going to explain a little more in detail. The testing framework I am working with compares what is defined in a json file to actual results of the test. So, in the above example, I am expecting the test to return a value of $416.67 Pre-Tax, and that is what I define as the expected result in the json file. The problem is that because the td element that contains this text separates the dollar amount and the tax value (Pre or post Tax) by a break, by using the locator for the td element, the test is only seeing the first value before the break (dollar amount). Now, if I get more granular with the xpath to where I define only the value after the break, I am getting the error that the xpath is objectText, and should be an element. So what I am looking for is a way to either define the break in the json so that the expected and actual values match (tried putting break in the json to no avail), or get the actual result of the test to return ignoring the break in the td element. Sorry if this is explained vaguely, it is quite difficult to convey without writing a novel.
Apologise if u don’t find this useful. You can extract the entire row,and then use regex to separate the the two parts inside.
Also have u used extract elements (notice the plural)by class name. This would return a list with matching elements(I hope this should work cause all the HTML elements have the same class name)

Find XPath of Text which is Under Div Tag and besides span tag

Sorry if this is discussed before. I tried searching it but didn't find exact match. My question is I have low HTML code,
<div class="column1">
<div>
<div class="name">
Dynamic Name
<span class="id" title="ID">Dynamic ID</span>
</div>
</div>
</div>
I am looking for XPath to get text Dynamic Name.
Here is what I tried which didn't work
1. //div/div[#class='name'] which is finding text Dynamic Name Dynamic ID
2. //div/span[#class='id']/preceding-sibling::text()
Since Dynamic Name & Dynamic ID, both are the dynamic value, I can't use split & use name as we don't know where to split it.
Thanks in advance for your time & help.
This XPath,
normalize-space(//div[#class="name"]/text())
will return "Dynamic Name" for your HTML, as requested.
Thanks but it has some syntax error as i tried putting on Firepath and its giving some error. not sure which one.
Wild guess: See if
//div[#class="name"]/text()
avoids your syntax error (which would be a limitation of your tool as normalize-space() is a proper XPath 1.0 function) and selects your targeted text (although with extraneous whitespace).
Since you stated that the XPath //div/div[#class='name'] is working but returns too much info, we can grab that element, grab the innerHTML, and then split on the first <, take the first String, and trim() it just in case to get the answer.
driver.findElement(By.xpath("//div/div[#class='name']")).getAttribute("innerHTML").split("<")[0].trim();

Not able to select a text using selenium

I have a readymade code and i'm trying to write tests for it using selenium. This is how my code looks like in element tab of chrome:
<table id="xyz">
<tbody>
<tr>...</tr>
"
I am not able to retrieve this text.
"
</tbody>
</table>
Doing this $x("//*[contains(text(),'I am not able to retrieve this text')]"); in console tab of chrome shows no results. I'm able to get text by this command if the text is defined in a div, span etc. (Also case sensitivity is not a problem).
In code that text is appended in tbody using jQuery('tbody').append( abc() ); and abc() function returns this text in this way pqr.html();
Now my questions is what xpath expression should i write to grab this text? And i am looking for a pure xpath expression i.e no java functions etc.
contains() expects singular value as the first parameter. An HTML element may have more than one text nodes children in it, in which case, your attempted XPath will evaluates only the first text node. According to the sample HTML posted, the first text node of <tbody> which will be evaluated consists of newline and some spaces, hence your XPath didn't consider <tbody> a match and returned no result.
To avoid the problem explained above, use contains() in predicate for individual text nodes like the following :
//*[text()[contains(.,'I am not able to retrieve this text')]]
or this way if you want to return the text node itself instead of the parent element :
//*/text()[contains(.,'I am not able to retrieve this text')]
That table element is probably within a frame. To access contents within a frame you need to first switch to it. You can use the "switch to" method in selenium. Refer this answer and this one.
For the same reason it is not working in the Chrome Dev Tools console. In the console tab, there is dropdown containing a list of frames. Make sure you select the correct frame in which the specific element exist and then execute your XPath.

Having trouble selecting some specific xpath... (html table, scrapy, xpath)

I'm trying to scrape data (using scrapy) from tables that can be found here:
http://www.bettingtools.co.uk/tipster-table/tipsters
My spider functions when I parse response within the following xpath:
//*[#id="imagetable"]/tbody/tr
Every table on the page shares that id, so I'm basically grabbing all the table data.
However, I only want the table data for the current month (tables in the right column).
When I try and be more specific with my xpath, I get an invalid xpath error even though it seems to be correct. I've tried:
- //*[#id="content"]/[contains(#class, "column2")]/[contains(#class, "table3")]/[#id="imagetable"]/tbody/tr
- //*[#id="content"]/div[contains(#class, "column2")]/div[contains(#class, "table3")]/[#id="imagetable"]/tbody/tr
- //*[#id="content"]/div[2]/div[1]/[#id="imagetable"]/tbody/tr
Also, when I try to select the xpath of a specific table on the page with chrome I just get //*[#id="imagetable"].
Am I missing something obvious here? Why are the 3 above xpath examples I've tried not valid?
Thanks
What makes those 3 invalid xpath is the part with this pattern :
/[predicate expression here]
above xpath missed to select a node on which the predicate would be applied. It should rather looks like this :
/*[predicate expression here]
Here are some examples of valid ones :
1. /table[#id="imagetable"]
2. /div[contains(#class, "column2")]
3. /*[contains(#class, "table3")]
For this specific task, you can try the following xpath which selects rows from table inside <div class="column2"> :
//div[#class='column2']//table[#id="imagetable"]/tbody/tr
Check my anwser Selenium automation- finding best xpath. In short check it by browser, browser can give U unique locator, then check it.