How to represent any text in text() method of xpath in selenium? - selenium

I have a text in a paragraph tag
<p class="lead ng-binding"> Showing all 50 toys available at Delhi store </p>
I used //*[normalize-space(text()) = 'Showing all 50 toys available at Delhi store'
and it located successfully, but what I need is the 50 and store name can be anything. So I need something which I can use to represent anything while locating this element. Any help is deeply appreciated. Thank you!

You can try below code to extract "50" from paragraph:
xpath = "//p[starts-with(normalize-space(text()), 'Showing all') and contains(normalize-space(text()), 'toys available at')]"
paragraph = driver.find_element_by_xpath(xpath)
value = paragraph.text.split("Showing all ")[-1].split()[0]
print(value) # "50"
XPath should allow you to fetch paragraph that starts-with "Showing all..." subsrtring and also contains "...toys available at..." substring, so you don't have to specify number and store name in XPath
P.S. As you didn't specify the programming language you use I provided example of solution in Python. Add appropriate tag if you want solution in specific language

Related

Selenium find element next to another one

I need to find an element that is located next to another one depending to an if condition.
For example, I'm trying to retrieve the bottom with the word “Log In & Pay” only if I found the words ‘DANA’ before.
I can find the first element with text DANA in this way, but how can I find then the next botton element with the text “Log In & Pay” ?
driver.findElement(By.xpath ("//*[contains(text(), 'DANA')]"));
Below the Html page:
Get the span with the desired text, find the closest ancestor div which contains both els, find the el you want from there. i.e.
//span[contains(text(), 'DANA')]
//ancestor::div[#class='web-pay-wallet-inside-wrap']
//div[#class='action']
/div[contains(text()='Log In & Pay')]
try using nested predicates
//div[span[contains(text(), 'DANA')]]/following-sibling::div[#class='action']/div
Explanation
//div[span[contains(text(), 'DANA')]] finds the div which contains span with text DANA
following-sibling::div finds the following div at the same level
Selenium 4 introduces relative locators which allow to look up elements in relative position to others. Like:
above
below
right of
left of
and even "near"
You can find examples here.

How to identify element by text when text is spanned over multiple lines using Selenium

Is it possible to write xpath using contains text such as(Below is what I want but does not work)
//ul[#role='listbox']/..//span[contains(text(),'Fast-Food Restaurent')]
Page Code:
<span class="item-title" md-highlight-text="searchText" md-highlight-flags="i">Fast-<span class="highlight">Food</span> Restaurant</span>
It is an auto complete text box when I enter the word food, there are some options and I want to select Fast-Food Restaurant from it.
Thanks in advance.
To identify the element you can use either of the following xpath based Locator Strategies:
Using the texts Food and Fast:
//ul[#role='listbox']/..//span[.//span[text()='Food']][contains(.,'Fast-')]
Using the texts Food and Restaurant:
//ul[#role='listbox']/..//span[.//span[text()='Food']][contains(.,'Restaurant')]
Using the texts Food, Fast and Restaurant:
//ul[#role='listbox']/..//span[.//span[text()='Food']][contains(.,'Fast-') and contains(.,'Restaurant')]
You can select required span node based on its string representation:
//span[.='Fast-Food Restaurant']
You can amend your path to the following:
//ul[#role='listbox']/..//span[contains(normalize-space(), 'Fast-Food Restaurant')]

xpath on the site is constantly changing

Peace. I registered a test on the amazon site. Doing a search of 11 iphone and then coming to a page of full products i choose first but its xpath
// span [contains (text (), 'Apple iPhone 11 (64GB) - Black')]
The problem is that I can use this xpath but tomorrow the xpath will be renamed because the first product is changed for example:
// span [contains (text (), 'Apple iPhone 11 Pro (64GB) - Space Gray')]
But I always choose the first product among all iphones even when the product changes?
Thanks.
This is the page
https://www.amazon.co.uk/s?k=iphone+11&crid=3GCCCW0Q2Z1MQ&sprefix=iph%2Caps%2C220&ref=nb_sb_noss_2
Use index and following xpath to get the first element.
(//a[#class='a-link-normal a-text-normal']/span)[1]
Always try to find something on the page that is very unlikely to change. If the element that you're looking for doesn't have such properties, look at it's ancestors.
For example, in this case, you can see that one of this span's ancestors have cel_widget_id="MAIN-SEARCH_RESULTS" which'll most likely remain constant. So, the following xpath:
//span[#cel_widget_id="MAIN-SEARCH_RESULTS"]//h2/a/span
will give you all such titles. You can get the first index as
(//span[#cel_widget_id="MAIN-SEARCH_RESULTS"]//h2/a/span)[1]
You could use the class of the search item span:
//span[#class="a-size-medium a-color-base a-text-normal"]
Then if you can do:
first_iphone = driver.find_element_by_xpath('//span[#class="a-size-medium a-color-base a-text-normal"]')
Although all search items are all the same class, (in this case a-size-medium a-color-base a-text-normal) the find_element_by_xpath method will only look for the first one.

Scrapy Xpath with text() equal to

import scrapy
example='<div class="ParamText"><span>OWNER APP</span></div>
<div class="ParamText"><span>OWNER</span></div>
<div class="ParamText"><span>OWNER NAME</span></div>'
scrapy.Selector(text=example).xpath('//*[#class="ParamText"]/span[contains(text(),"OWNER")]').extract_first()
Here I need to scrape OWNER only sometimes 3 span I will get OWNER
output:
I am getting: OWNER APP
I want: OWNER
You can use the regular expression ^OWNER$ to match spans containing only OWNER.
Replace contains(text(),"OWNER") with re:test(text(),"^OWNER$").
The advantage of regular expressions is that you could also allow for spaces (^\s*OWNER\s*$) or support different letter cases ((?i)^OWNER$).
scrapy.Selector(text=example).xpath('//*[#class="ParamText"]/span/text()').extract()[1]
You can select by text equation like scrapy.Selector(text=txt).xpath('//*[#class="ParamText"]/span[text()="OWNER"]').get() or without span details, it will give you the first one: scrapy.Selector(text=txt).css('div.ParamText span').get()

How to extract the text within an HTML tag (in Selenium IDE)?

The html looks something like this:
<p>
sometext1
<br>
sometext2
<br>
sometext3
</p>
I would like to extract all the text between the paragraph tags, including the <br> tags.
I tried to use storeText function, but it stores only the text, without the tags.
I could store the entire HTML source and then extract what I need in Perl, but I was wondering if there is a way to store a block of HTML code using a specific xpath (e.g. store the HTML code for the third table in the webpage inside a variable).
innerHTML
i will try with document.getElementById('id').innerHTML
you could use a getEval() with Javascript that return the innerHTML of the element. You'll have to find it in javascript, though
#Tarun: I would if I could man....
#Grooveek: Thanks man, that worked.
I used:
storeEval | window.document.getElementsByTagName("p").item(9).innerHTML | p
This saved the content of the 9th paragrah in the variable p.
I had to use getElementsByTagName because the tags had no id's.
For more accuracy, one could use getElementById function insted:
storeEval | window.document.getElementById("id of element").innerHTML | p
Hope this will help other people too.
Thanks again.
I suggest this:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("url")
element = driver.find_element_by_tag_name("p")
text = element.text
But keep in mind if you are dealing with text-boxes, you can't use .text; it returns None. In that case you should use .get_attribute("value"), and when ever you are unable to catch what you want, you can use .get_attribute("innerHTML").
getAttribute("innerHTML"); works for me
I propose to find it by a class name, not all objects have it's Id.
storeEval | window.document.getElementsByClassName('*classname*')[0].innerHTML; | HTMLContent
number 0 will return first occurence. If there is more than one element, choose proper number, or get the number of class occurencies by .length
storeEval | window.document.getElementsByClassName('*classname*').length; | ClassCount