I'm using an xpath to locate element that contains a certain text in it. My problem is that it locate another element that have the same text i'm looking for in it but also some other text, here the xpath i'm using is:
//a[contains(text(), 'Workflow')]
And i want to locate a link that contain the text Workflow and Workflow only,
but the xpath locate a link with Workflow.MAINMENU wich i don't want to.
Is this possible with an XPATH ?
Yes, this is possible. You need to not use the contains function, but to instead compare the text directly:
//a[text() = 'Workflow']
If there is whitespace surrounding the text, you could use:
//a[normalize-space(text()) = 'Workflow']
Related
I have many spans with different text. But I need to find a span with a long text with a certain word inside this text.
<div class="commentMessage">
<span>Any endgame spoilers</span>
</div>
In this case, I want to choose a span contains text with a certain word 'endgame'.
Here's what I tried:
//div[#class='commentMessage']/span[text()='endgame'] - but it show no results (very strange) =\
then I tried to find the span using all phrase:
//div[#class='commentMessage']/span[text()='Any endgame spoilers'] - and it works =\
But as I said I need to find a span using a certain word in it.
Also, I tried that construction:
//div[#class='commentMessage']/span[contains(text(), 'endgame')] - but Chrome xPath extension says: Type is not appropriate for the context in which the expression occurs
Try the following xpath.
//div[#class='commentMessage']/span[contains(.,'endgame')]
<a href="javascript:void(0)" title="home">
<span class="menu_icon">Maybe more text here</span>
Home
</a>
So for above code when I write //a as XPath, it gets highlighted, but when I write //a[contains(text(), 'Home')], it is not getting highlighted. I think this is simple and should have worked.
Where's my mistake?
Other answers have missed the actual problem here:
Yes, you could match on #title instead, but that's not why OP's
XPath is failing where it may have worked previously.
Yes, XML and XPath are case sensitive, so Home is not the same as
home, but there is a Home text node as a child of a, so OP is
right to use Home if he doesn't trust #title to be present.
Real Problem
OP's XPath,
//a[contains(text(), 'Home')]
says to select all a elements whose first text node contains the substring Home. Yet, the first text node contains nothing but whitespace.
Explanation: text() selects all child text nodes of the context node, a. When contains() is given multiple nodes as its first argument, it takes the string value of the first node, but Home appears in the second text node, not the first.
Instead, OP should use this XPath,
//a[text()[contains(., 'Home')]]
which says to select all a elements with any text child whose string value contains the substring Home.
If there weren't surrounding whitespace, this XPath could be used to test for equality rather than substring containment:
//a[text()[.='Home']]
Or, with surrounding whitespace, this XPath could be used to trim it away:
//a[text()[normalize-space()= 'Home']]
See also:
Testing text() nodes vs string values in XPath
Why is XPath unclean constructed? Why is text() not needed in predicate?
XPath: difference between dot and text()
yes you are doing 2 mistakes, you're writing Home with an uppercase H when you want to match home with a lowercase h. also you're trying to check the text content, when you want to check check the "title" attribute. correct those 2, and you get:
//a[contains(#title, 'home')]
however, if you want to match the exact string home, instead of any a that has home anywhere in the title attribute, use #zsbappa's code.
You can try this XPath..Its just select element by attribute
//a[#title,'home']
I have already learned to use xpath but i am kind of stuck here - http://phptravels.com/requirements/. Can anyone please tell me how to find xpath of "Demo" hyperlink on this website. I simply used //a[text()= 'Demo ']. keep whitespaces in mind.
Try to bind the xpath with an id which is persistent, you can consider using this xpath:
//nav[#id='main-menu']/ul/li/span/span/a[contains(text(), 'Demo')]
The white space is your problem. Use contains instead of equality
//a[contains(text(), 'Demo')]
Or
//a[contains(., 'Demo')]
Here with equals, but better to use contains (or starts-with), as described #Guy
driver.findElement(By.xpath("//a[text()='Demo\n ']")).getText();
to get real text value of element - you can use this:
driver.findElement(webElement).getAttribute("text")
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.
So I've got some li on a page and I'm trying to identify it with some XPATH, only trouble is I need to make sure that all the text matches so I need to identify on all the text and there is a in there that is giving me hassle (I'm using a chrome addin to validate the XPATH and it keeps telling me its null when I try), any suggestions welcome!
Here is the html on the page: -
<li>
Some pre text, <b>bold</b> nothing here is identified.
</li>
Here is what I've tried that doesnt work: -
//ul/li[contains(text(),'') and contains(text(),'bold') and contains(text(),'nothing here is identified')]
I also tried this just to see if it works (bear in mind my XPATH needs to check all the text within that li), but it won't identify it at all using any text after the bold tags...
//ul/li[contains(text(),'nothing here is identified')]
What obvious XPATH trickery and I missing...?
Cheers
You can use the following:
//ul/li[contains(.,'') and contains(.,'bold') and contains(.,'nothing here is identified')]
Use of text() would give you three text nodes, as there are 3 nodes infact, which when used in contains() will be an irrecoverable error:
Some pre text,
bold
nothing here is identified.
But the use of . or current()(both mean the same here), would give you only one string(concatenation of all three nodes mentioned above).