how to get text from text node without getting content of siblings - selenium

I have following code
<div>
<p>some paragraph</p>
some nasty text that I need
<span>something else</span>
</div>
Now I need to get some nasty text that I need only. How to do it using only XPath 1.0? Is it possible?

How to do it using only XPath 1.0? Is it possible?
Yes - and it's rather trivial:
/div/text()
I wonder why you did not try that? All other text nodes are either in a p or span element and should not cause you any trouble.

Related

Selenium XPATH selecting next sibling

<div class="block wbc">
<span></span>
<span> text_value </span>
</div>
for getting text in second span where does below code go wrong?
driver.find_element(X_PATH,"*//div[#class='block']/span[1]")
For trying by yourself, maybe I write sth wrong here is link
https://soundcloud.com/daydoseofhouse/snt-whats-wrong/s-jmbaiBDyQ0d?si=233b2f843a2c4a7c8afd6b9161369717&utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing
And my code; still giving an error
playbackTimeline__duration =driver.find_element(By.XPATH,"*//div[#class='playbackTimeline__duration']/span[2]")
For finding web element clearly:
//*[#id="app"]/div[4]/section/div/div[3]/div[3]/div/div[3]/span[2]
But I will not use this way, I need declare with class method or CSS Selector at least
If you are sure that you always need the second span use this XPath:
*//div[#class='playbackTimeline__duration']/span[2]
If you need the first span that has actual text use this:
*//div[#class='playbackTimeline__duration']/span[normalize-space()][1]
If the #class has more than only playbackTimeline__duration in it you can use:
*//div[contains(#class,'playbackTimeline__duration')]/span[2]
If there are more div's like that use:
*//div[contains(#class,'playbackTimeline__duration')][1]/span[2]

Could you help me with xpath of a similar html structure?

<div>
<div>
<div>
<h1 >text1<h1>
<div>
<div>
<div>
<div>
<p> some text <p>
I would like to have the XPath for <p>some text<p> which follows <h1>text1<h1>
Depending upon how much you know about the structure, you could make the XPath a bit more specific, and if you need to worry about whitespace decide whether you could use = or should use contains(), or normalize the whitespace with normalize-space() before comparing.
However, first identify the h1 element, and then use the following:: axis to target the p:
//h1[. = "text1"]//following::p[contains(text(), "some text")]
Not totally clear if those divs the OP is showing are on the same level, but when they are and you don't want to be depend on amount of nested div's, you could use:
//div[.//h1[contains(text(),'text1')]]/following-sibling::div//p[contains(.,'some text')]
If you can depend on amount of nested divs then the following XPath wil certainly perform better
//div[div/div/h1[contains(text(),'text1')]]/following-sibling::div/div/div/div/p[contains(.,'some text')]
In case the "some text" is unique you can simply use the following XPath
//p[contains(text(),'some text')]
or
//*[contains(text(),'some text')]
or
//p[text()='some text']
or
//*[text()='some text']
If you want to write Xpath of some text based on text1.
Xpath :
//h1[contains(text(),'text1')]/following-sibling::h1/descendant::p[last()]/preceding-sibling::p
Read more about xpath Axes here
This will be the xpath of the above p tag contains "some text"
//div//div//div//div//p

Selenium Python, extract text from node and ALL child nodes

I have the opposite problem described here. I can't get the text more than one layer deep.
HTML is structured in the following manner:
<span class="data">
<p>This text is extracted just fine.</p>
<p>And so is this.</p>
<p>
And this.
<div>
<p>But this text is not extracted.</p>
</div>
</p>
<div>
<p>And neither is this.</p>
</div>
</span>
My Python code looks something like this:
el.find_element_by_xpath(".//span[contains(#class, 'data')]").text
Try the same with child elements:
print(el.find_element_by_xpath(".//span[contains(#class, 'data')]").text)
print(el.find_element_by_xpath(".//span[contains(#class, 'data')]/div").text)
print(el.find_element_by_xpath(".//span[contains(#class, 'data')]/p").text)
Not sure what's the referred el in your original post. But able to get all the text using the below.
driver.find_element_by_xpath("//span[#class='data']").text
Output:
'This text is extracted just fine.\nAnd so is this.\nAnd this.\nBut this text is not extracted.\nAnd neither is this.'
Instead of relying on WebElement.text property consider querying innerText property
Consider using Explicit Wait as it will make your test more robust and reliable in case if the element you're looking for is loaded by i.e. AJAX call
Assuming all above:
print(WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//span[#class='data']"))).get_attribute("innerText"))
Demo:

Xpath for node without text but child has text

I am having an issue trying to find a node that doesnot have text but their child has an specific text.
Here is an example of the html code:
<strong>
This is not
<span>the one</span>
</strong>
<strong>
<span>the one</span>
</strong>
So I need to find the second strong.. but the xpath that I am using is this one:
//strong/span[text()='the one']
This brings me the two elements ... but I need the second one.
I tried something like this:
//strong[not(text())]/span[text()='the one']
but it didn't work..
Any idea how to accomplish this?
Try this one:
//strong[not(normalize-space(text()))]/span[text()='the one']
Use Index to identify the position. But note that here indices start from 1.
(//strong/span[text()='the one'])[2]

Unable to retrieve the text inside the div tag even when the tag is identified

I am trying to retrieve the text embedded inside the div tag. Partial html code is given below. I consulted the other existing answers, but the tag is located successfully but the text is coming back as empty string.My purpose is to retrieve the string between the 'div' tag as "You entered an invalid username or password, please try again."
I used the xpath
//div[#class='login-card js-login-card']/div[#role='alert']/div[2]
I used the css
.alert__heading.js-alert--error-text
This only getting back the tag name as div, but the text as an empty string.
Any ideas or corrections?
<div class="login-card js-login-card">
<div class="login-page__alert alert alert--error tt js-alert--error" role="alert">
<div class="alert__icon">
<div class="alert__heading js-alert--error-text">You entered an invalid username or password, please try again. </div>
</div>
<div id="cmePageWrapper" class="page-wrapper page-wrapper--card"> </div>
Try following xpath, as the required div tag is child node of div with class 'alert__icon':
//div[#class='login-card js-login-card']/div[#role='alert']/div[1]/div
Let me know, if it works for you.
Maybe you wanna try this
div[class*="error-text"]
If it didn't work try to get text by executing javascript code using this
$$( "div[class*="error-text"]" ).text() OR .val()/.html()
Good luck !
You could use contains with xpath, something like //div[contains(#class, 'error-text' ) ], using findelement will retrieve first element match the criteria. If it still returns empty, it means that the page might have more than one element which match the criteria