unable to get xpath of anchor element under span element - html

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

Related

Xpath: Get Text After Element With Containing Text

I am looking for a way to get text which is not inside an HTML element:
<div class="col-sm-4">
<strong>Handelnde Personen:</strong><br><br>
<strong>Geschäftsführer</strong><br>
Mr John Doe<br>
Privatperson<br>
.....<br>
<br>
I want to get "Mr John Doe".
The only way I see is looking for a strong element which contains "Geschäftsführer" and then look for the following text.
My idea so far:
//strong[contains(text(), 'Gesch')]/br/../text()
... I simply can't make it work.
Also, is there a "wildcard" for strings? That I could use
*esch*ftsf*hr*
for "Geschäftsführer"?
I highly appreciate your help, thanks!
Try
//strong[starts-with(., 'Gesch')]/following-sibling::text()[1]
As for wildcard matching, with XPath 2.0 you use regular expressions:
//strong[matches(., '.*esch.*ftsf.*hr.*')]
With XPath 3.0 you could also use the Unicode collation algorithm
//strong[compare(., 'Geschäftsführer',
'http://www.w3.org/2013/collation/UCA?strength=primary') = 0]
(strength=primary ignores case and accents)
But to get anything more advanced than XPath 1.0 in the browser, you would need to deploy Saxon-JS.
Another option with 1.0 is to use translate() to remove case and umlauts:
//strong[translate(., 'ABCD..XYZÄÖÜäöüß', 'abcd..xyzaouaous') = 'geschaftsfuhrer']
Note, in all these examples I have used "." rather than "text()" to get the string value of an element - this is recommended practice.

Xpath that find a specific text and only this specific text

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']

is it possible to read the text of a li using Xpath with different attributes?

I am aware that I can directly use:
driver.FindElement(By.XPath("//ul[3]/li/ul/li[7]")).Text
to get the text .. but I am trying get the text by using Xpath and combination of different attributes like text(), contains() etc.
//ul[3]/li/ul/li//[text()='My Data']
Please suggest me different ways that I can handle this ... except the one I mentioned.
<li class="ng-binding ng-scope selectedTreeElement" ng-click="orgSelCtrl.selectUserSessionOrg(child);" ng-class="{selectedTreeElement: child.organizationId == orgSelCtrl.SelectedOrg.organizationId}" ng-repeat="child in node.childOrgs" style="background-color: transparent;"> My Data </li>
looks like you have extra "/" in your xpath and you miss dot:
//ul[3]/li/ul/li//[text()='My Data']
try this:
.//ul[3]/li/ul/li[text()='My Data']
BUT you are use xpath only for find elements, but not for reading its attributes. If you need to read attribute or text inside of it, you need to use selenium after search.
.Text of a WebElement would just return you the text of an element.
If you want to make expectations about the text, check the text() inside the XPath expression, e.g.:
//ul[3]/li/ul/li[text()='My Data']
or, using contains():
//ul[3]/li/ul/li[contains(text(), 'My Data')]
There are other functions you can make use of, see Functions - XPath.
You can also combine it with other conditions. For instance:
//ul[3]/li/ul/li[contains(#class, 'selectedTreeElement') and contains(text(), 'My Data')]

Using XPATH to find a li based on text contains doesnt work on text after a <b> tag

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

XPath: "Exclude" tag in "InnerHtml" (InnerHtml<span>excludeme</span>

I am using XPath to query HTML sites, which works pretty good so far, but now I hit a (brick)wall and can't find a solution :-)
The html looks like this:
<ul>
<li>Text1<span>AnotherText1</span></li>
<li>Text2<span>AnotherText2</span></li>
<li>Text3<span>AnotherText3</span></li>
</ul>
I want to select the "TextX" part, but NOT the AnotherTextX part in the <span></span>
So far I couldn't come up with any (pure) XPath solution to do that (and in my setup I unfortunately need a pure XPath solution.
This selects kind of what I want, but it results in "TextXAnotherTextX" and I only need "TextX".
/ul/li/a
Any hints? :-)
This gets you the first direct text node child of <a>:
/ul/li/a/text()[1]
and this would get you any direct text node child (separately):
/ul/li/a/text()
Both of the above return "TextX", but if you had:
<li>Text4<span>AnotherText3</span>TrailingText</li>
then the latter would return: ["Text4", "TrailingText"], while the former would return "Text4" only.
Your expression /ul/li/a gets the string value of <a>, which is defined as the concatenation of the string value of all the children of <a>, so you get "TextXAnotherTextX".