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

<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

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]

how to find xpath of the input box in the following HTML

I have a html like this
<td class="random">
<div id="randomID">Product:</div>
</td>
<td class="random">
<div id="randomID">
<input type="text" class="random">
</div>
</td>
my xpath //div[contains(text(),"Product:")] gives me the first element for which I want to send input. How do I get the input xpath so I can do input.sendkeys() on it.
You use either of the xpath to get the input tag.
Use following and index of input tag
//div[contains(text(),"Product:")]/following::input[1]
Or find the td tag and then use following-sibling
//td[.//div[contains(text(),"Product:")]]/following-sibling::td[1]//input
You can use below xpath as well.
//div[text()="Product:"]/following::input[1]
Or
//td[.//div[text()="Product:"]]/following-sibling::td[1]//input
Use following-sibling
Try with following xpath:
//td[contains(.,"Product:")]//following-sibling::td//input
For the provided code, the input is very simple to identify:
//input[#class='random']
Since I can't see any other duplicate code to force you to be more precise, I don't see the problem in using this one.
If you have multiple , and each or some of them have an input inside, in this case:
//div[text()="Product:"]/following::input[1]
Where Product is the visible text of the div that you want to use as a parent, and then you go straight in the first input taken by its index.

Selenium preceding returns a pointer/address and full xpath return a different pointer/address to what I believe should be the same object

Relative Xpath
WebElement precedingClass = driver.findElement(By.xpath("//div[contains(#class, 'pictures')]/preceding::div[contains (#class 'monkey picture') ]"));
Absolute Xpath
WebElment fullXpathAddress = driver.findElement(By.xpath("/html/body/div[6]/div/div[1]/div[1]/div/div[2]/ul/li[20]/div[1]");
HTML Code:
<div class="pictures">
<a ref ....>
<a ref ....>
<h1>x's pictures</h1>
</div>
<div class="animals">
<div class="monkey picture" title="happy monkey"></div>
.
.
</div>
Preceding: Select all nodes that come before the current node.
And you want to select node that is after the current node.
Maybe you can use following as below :
"//div[contains(#class, 'pictures')]/following::div[#class='animals']/div[#class='monkey picture']"
please refer this link to learn more about Xpaths
Please optimize the above Xpath based on your whole DOM structure.
Your Xpath seems wrong
Try below Xpath:
//div[#class='pictures']/following-sibling::a//div[#class='monkey picture']
So the code will be like:
WebElment element = driver.findElement(By.xpath("//div[#class='pictures']/following-sibling::a//div[#class='monkey picture']");
I was able to use preceding::div[x] since I was able to determine index of div "monkey picture" in the list of animals and from the start of animals, the number of divs preceding to "pictures was a fixed value.

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:

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

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.