Unable to find element using the following Xpath - python

I am trying to find the input type with statusid_103408 and with text() Draft
here is the xpath i am using, not sure where I am going wrong
//input[#name='statusid_103408' and contains(text(), 'Draft')]

The reason this xpath does not work is because the text of "Draft" is not actually a property of the input element. It is contained in the li element that is the parent. Therefore, your search is returning no results.
I suggest just using the name only in your xpath search (if it unique). If you definitely need the text in your search, you can search the li item's text first, then find your input, like so:
//li[text()='Draft']/input[#name='statusid_103408']

Use Value it will work , because value is unique, text is not inside the input tag!

Related

In Playwright (Python) when there are multiple buttons on a page, all with the same name, how do i select correct button?

If I am implementing string locators, such as:
continue_button: str = "button:has-text(\"Continue\")"
If there are multiple buttons on the same page that say continue, but are for different paths, how do I select the correct continue... is there a way to add an index to that string locator?
There is several good practices for creating locators/selectors.
Using playwright there is official documentation for each common and unique selector on how-to and what-is doing.
More information in https://playwright.dev/docs/selectors#text-selector
About your case, i would suggest always to use an parent selector for locating an element.
When there is a button, try to find its unique parent.
By id
By unique class
Something else unique.
Example:
<dv id=test>
<button id=continue-test>Continue</button>
</div>
In this case you can use the unique id of the button and not the text.
Selector css: #continue-test
But if you, don't have an unique identifier for the button you can use the parent and go down to the button.
Selector css: #test > button
Matching text using css is not possible, but with XPATH can look like this:
//button[text()="Continue"]
This selector MATCHES the text using "equals".
Using playwright:
button:has-text("Continue")
Using has-text and quotes - matches the text using equals.
If you are using another selector for example text=Continue, this will match all elements that CONTAINS the text "Continue"
All this is explained with example in the official documentation for playwright selectors.
That does not mean to not use XPATH to achieve the goals.
CSS selectors are fast but kind of restricted to work with text.
Xpath is quite slower but much more powerful to work in text/parent/child elements etc.
I would suggest always to use an parent element with unique identifier and go down to reach your actual element, which will receive the interaction.
The fact that I love Playwright is because of scenarios like this and how easily it can be handled.
If you have a string named abc and there are multiple occurrences of that string on a single page, then you can use the nth-match criteria to pick the nth element.
For eg ,
await page.locator(':nth-match(:text("abc"), 3)').click();
will select the 3rd occurrence of the word abc. Similarly, in your case, if you want to select the first or second or third, you can simply do
await page.locator(':nth-match(:text("Continue"), 1)').click();
await page.locator(':nth-match(:text("Continue"), 2)').click();
await page.locator(':nth-match(:text("Continue"), 3)').click();
Please refer to the Selectors documentation for Playwright -> Selectors
This is different than the nth-child concept as mentioned
Unlike :nth-child(), elements do not have to be siblings, they could
be anywhere on the page. In the snippet above, all three buttons match
:text("Buy") selector, and :nth-match() selects the third button.

xpath to check only within WebElement in Selenium / Python

I am very new to this and i have tried to look for the answer to this but unable to find any.
I am using Selenium+chromedriver, trying to monitor some items I am interested in.
Example:
a page with 20 items in a list.
Code:
#list of items on the page
search_area = driver.find_elements_by_xpath("//li[#data-testid='test']")
search_area[19].find_element_by_xpath("//p[#class='sc-hKwDye name']").text
this returns the name of item[0]
search_area[19].find_element_by_css_selector('.name').text
this returns the name of item[19]
why is xpath looking at the parent html?
I want xpath to return the name of item within the WebElement /list item. is it possible?
found the answer, add a . in front
hope this is gonna help someone new like me in the future.
from
search_area[19].find_element_by_xpath("//p[#class='sc-hKwDye name']").text
to
search_area[19].find_element_by_xpath(".//p[#class='sc-hKwDye name']").text
What you are passing in find_element_by_xpath("//p[#class='sc-hKwDye name']") is relative Xpath. You can pass the full Xpath to get the desired result.

How to check if matched text in web element is partially enclosed in <a> tag?

I have the following:
This is my text string and this next <a href='https//somelink.org/'>part</a> is only partially enclosed in a tags.
In the above string i have to search for "next part" not only "part" so once i find the "next part" I need to check if there is any a tag present in the matched text (sometimes there is not an tag) - how can I do that?
Additional to my main question I can't make my xpath to work to find "next part" in the elements.
I tried this:
//*[contains(text(),"next part")]
But it doesn't find anything probably because I have spaces in there - how do I overcome this?
Thank you in advance,
Let's assume this html:
<p>This is my text string and this next <a href='https//somelink.org/'>part</a> is only partially enclosed in a tags.</p>
We can select with selenium:
p = driver.find_element_by_xpath('//p[contains(.,"next part")]')
And we can determine if it's partly in an a tag with regex (Tony the Pony notwithstanding):
html = p.get_attribute('innerHTML')
partly_in_a = 'next part' in re.sub(r'</?a.*?>', '', html) and 'next part' not in html
There's no pure xpath 1.0 solution for this, and it's a mistake in general to depend on xpath for stuff like this.
You'll need to use a nested XPath selector for this.
//*[contains(text(), 'next') and a[contains(text(), 'part')]]
This will query on any element that contains text next, then also check that the element contains nested a element with text part.
To determine whether or not there actually IS a nested a tag, you will need to write a method for this that checks against two different XPaths. There is no easy way around this, other than to evaluate the elements and see what's there.
public bool DoesElementHaveNestedTag()
{
// check for presence of locator with nested tag
// if driver.findElements returns > 0, then nested tag locator exists
if (driver.findElements(By.XPath("//*[contains(text(), 'next') and a[contains(text(), 'part')]]")).Count > 0) return true
else return false
}
You can change this method to fit your needs, but the idea is the same. There is no way to know if a WebElement has a nested tag or not, unless you try to find the WebElement using two XPaths -- one that checks for the tag, and one that does not.

How to Collect the line with Selenium Python

I want to know how I can collect line, mailto link using selenium python the emails contains # sign in the contact page I tried the following code but it is somewhere works and somewhere not..
//*[contains(text(),"#")]
the emails formats are different somewhere it is <p>Email: name#domain.com</p> or <span>Email: name#domain.com</span> or name#domain.com
is there anyway to collect them with one statement..
Thanks
Here is the XPath you are looking for my friend.
//*[contains(text(),"#")]|//*[contains(#href,"#")]
You could create a collection of the link text values that contain # on the page and then iterate through to format. You are going to have to format the span like that has Email: name#domain.com anyway.
Use find_elements_by_partial_link_text to make the collection.
I think you need 2 XPath. First XPath for finding element that contains text "Email:", second XPath for element that contains attribute "mailto:".
//*[contains(text(),"Email:")]|//*[contains(#href,"mailto:")]

Select by xpath knowing only ending of element's attribute

Having such xml file. How can I select only that tag, which href attribute ends with parent, like third element below.
Determine it by position like
elem = tree.findall('{*}CustomProperty')[2]
does not fit because some documents might have only one parent href, others 5-10 and third might not have such hrefs at all.
I tend to use xpath but can not figure out how can I tell xpath to search for end of attribute match.
Also xpath is not must, I will be glad to use any way that fits to my purpose
So how can I get CustomProperty element which has a href attribute that ends with word parent ?
<CustomProperty href="urn:1653267:643562dafewq:cs:46wey5ge:234566">urn:1653267:643562dafewq:cs:46wey5ge:234566:ss</CustomProperty>
<CustomProperty href="urn:1653267:643562dafewq:cs:46wey5ge:234566">urn:1653267:643562dafewq:cs:46wey5ge:234566:ss</CustomProperty>
<CustomProperty href="urn:1653267:643562dafewq:cs:46wey5ge:234566:parent">urn:1653267:643562dafewq:cs:46wey5ge:234566:ss</CustomProperty>
Thank you in advance for help
Try using the contains selector to find the element with an attribute href which contains the word parent
//*[contains(#href, 'parent')]
or if you are sure about the position of text "parent" you can use the ends-with
//*[ends-with(#href, 'parent')]
Does
//CustomProperty[contains(#href, 'parent') and substring-after(#href, 'parent') = '']
cater to your requirements? One issue with the suggestion is that it fails for href attributes where parent occurs more than once.
If your xpath processor supports xpath 2.0, use aberna's suggestion.
Remember to replace the '//' axis by specific paths whereever possible for performance reasons.

Categories