How to write the XPath using sibling? - selenium

How to write the XPath using sibling?
I am trying to get the price value of the delivery fee using the sibling. But I am unable to get the XPath for the price tag below is the HTML code.
<div class="grid_3 d-grid_10">
<label class="m-confirmation-modal-print-detail-capgrey"> Delivery Fee:</label>
</div>
<div class="grid_1 d-grid_2">
<label class="m-confirmation-modal-print-price text-align-right"> $9.00</label>
</div>

You can try this:
//div[contains(., ' Delivery Fee:')]/following-sibling::div/label
Explanation to xPath: //div[contains(., ' Delivery Fee:')] finds a div on the top, then /following-sibling::div will select all next siblings div below our div. In our case only the next div. And finaly /label locates the element with value $9.00.
More information here

You can try this :
//label[contains(text(),' Delivery Fee:')]/parent:div/following-sibling::div/label
But yes #Andrei solution make much sense to use.

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]

Find Xpath to an element depending on the value of another element in a table row

I'm new to Xpath so if this doesn't contain all relevant information apologies & let me know what you need to solve it.
I am trying to find an Xpath to an "expand arrow" element which expands a row in a table. The "expand arrow" element isn't unique so I would like to select it based on text contained in another element on the same row. The layout is as follows:
<td id="__table2-rows-row10-col0">
<div class="sapUiTableCellFlex">
<span id="__table2-rows-row10- treeicon" title="Expand Node" role="button">
<div id="__hbox27-__clone101">
<div id="__data70-__clone101">
<div id="__data71-__clone101">
<span id="__text47-__clone101" title="sys-admin">sys-admin</span>
I'd like to select the element with title = "Expand Node"
<span id="__table2-rows-row10- treeicon" title="Expand Node" role="button">
based on the element with title or text = "sys-admin"
<span id="__text47-__clone101" title="sys-admin">sys-admin</span>
I've played around with various options but I can't seem to get it to work. Any ideas would be much appreciated!
Thanks
To locate the element with title as Expand Node with respect to the element with title or text as sys-admin you can use either of the following Locator Strategies:
xpath and title attribute:
"//span[#title='sys-admin']//ancestor::span[#title='Expand Node']"
xpath and text() attribute:
"//span[text()='sys-admin']//ancestor::span[#title='Expand Node']"
I eventually got it to work using the following xpath:
//span[#title='sys-admin']/../../preceding-sibling::span[#title='Expand Node']

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.

How to match xpath for id element that changes each time page loads?

I have these 2 xpath that are different each time I load a webpage.
The xpaths were recorded by Selenium-IDE and always have mainForm_view within the id string and the text before and after this always changes.
xpath=//input[#id='abc_hyd_wuu2_8333nd_mainForm_view_jjd_uueue2_jjd_11_jkdhd']
xpath=//div[#id='abc_hyd_wuu2_8333nd_mainForm_view_kcjjcs_sjsjs_jjdj_994_kkk']/div/div[2]/div/div/div/a[1]/h2
I've tried to locate the id like below but doesn't work.
xpath=//input[contains(#id,'mainForm_view')]
xpath=//div[contains(#id,'mainForm_view')]
Which would be the correct way to do it?
Thanks in advance.
UPDATE
I've tried with CSS selector like below but it seems is taking another id that is within an input element
document.querySelector("input[id*='mainForm_view']").id
Examining the html code I see that the id I need is related with a unique class. The code is like below:
<div class="Class_p2">
<div class="Class_p3" style="...">
<input name="8333nd$mainForm$view$jjd$uueue2" type="text" class="class a1 n1-Control" value="xyz" id="8333nd_mainForm_view_jjd_uueue2" disabled="disabled" style="..">
</div>
<input name="8333nd$mainForm$view$ttyi" type="text" disabled="disabled">
</div>
I've tried the following Javascript code in Chrome console but it doesn't work
document.getElementsByClassName("class a1 n1-Control").id
How would be to get the id=8333nd_mainForm_view_jjd_uueue2 that is related with Class=class a1 n1-Control?
UPDATE2
I was finally able to do it with
document.getElementsByClassName("class a1 n1-Control")[0].id
Thanks for all the help and time.
You can write css selector as :
input[id*='mainForm_view']
for div it'd be :
div[id*='mainForm_view']
Asterisk is to match the sub string part.
Note that if any id contains mainForm_view that will also be selected, so better to check in developers tool before proceeding.
You can try finding some other element for which xpath/css locator remains same and then try to reach to this element by traversing from there. You can use parent, ancestor, preceding-sibling, following-sibling keywords in order to traverse. Hope it helps :)

How to write Xpath for next Div using Sibling

I want to read the Tax Price using the sibling concept, so I have I've written below XPath, but it's not working
My code:
//div[#class='grid_3 d-grid_10']//label[contains(text(), 'Tax')]/following-sibling::div
HTML:
<div class="grid_3 d-grid_10">
<label class="m-confirmation-modal-print-detail-capgrey"> Tax:</label>
</div>
<div class="grid_1 d-grid_2">
<label class="m-confirmation-modal-print-price text-align-right"> $10.50</label>
</div>
To read the Tax Price i.e. $10.50 using text Tax within the ancestor node, you need to locate the <label> node with text as Tax: first. Then with respect to this node you need to locate the following <div> node which have a decedent node containing the required text i.e. $10.50 and to achieve that you can use the following solution:
XPath:
//label[#class='m-confirmation-modal-print-detail-capgrey' and contains(.,'Tax')]//following::div[1]/label
The second <div> is a sibling of the first one, not of the child <label>. You need to go back to the parent <div> first using .. or parent::div
//div[#class='grid_3 d-grid_10']//label[contains(text(), 'Tax')]/parent::div/following-sibling::div
As suggested in the comments you can simplify it by starting the xpath with the "Tax" <label>
//label[contains(text(), 'Tax')]/parent::div[#class='grid_3 d-grid_10']/following-sibling::div
You can use this :
//label[contains(text(), 'Tax')]/../following-sibling::div