Reputation: 2940
I'm trying to replicate what was done in this answer for java selenium in RSelenium: https://stackoverflow.com/a/27611777/7837376
I'd love to be able to do something like this:
#replicating simple RSelenium process getting all //a elements
library(RSelenium)
#start remDr etc. etc.
all_a <- remDr$findElements(using='xpath','//a')
selected_a <- all_a[[10]]
Ideally then I could generate the xpath of the selected_a element using the made up function below:
#desired function
getElementXPATH(selected_a)
I understand that quite a few different XPATH's could be specified for the same element, I'm just looking for a unique xpath identifier for the element, so any unique xpath to the element will suffice!
Thanks!
Upvotes: 1
Views: 484
Reputation: 13
Please try the below logic
function absolutePath(element) {
if (element.tagName.toLowerCase() == 'html')
return '/html[1]';
if (element === document.body)
return '/html[1]/body[1]';
var ix = 0;
var siblings = element.parentNode.childNodes;
for (var i = 0; i < siblings.length; i++) {
var sibling = siblings[i];
if (sibling === element)
return absolutePath(element.parentNode) + '/' + element.tagName.toLowerCase() + '[' + (ix + 1) + ']';
if (sibling.nodeType === 1 && sibling.tagName.toLowerCase() === element.tagName.toLowerCase())
ix++;
}}
I did try the solution provided by supputuri, but it doesnt work on all cases. Example: Try the function provided by @suppututri on https://www.amazon.in/ , and try to find the absolute xpath for
var element=document.querySelector('#nav-xshop > a:nth-child(2)');
getAbsoluteXpath(element);
The incorrect xpath shown in the console would be: "//HTML/BODY/DIV[1]/HEADER/DIV[1]/DIV[68]/DIV[9]/DIV[1]/DIV/A[1]"
Upvotes: 0
Reputation: 14145
Personally, I am not a big fan absolute xpath. However, you can get the absolute xpath using javascript rather having the function in your language, which will ran faster and it's easy to port.
Here is the javascript.
// this function will return the absolute xpath of any given element
jsFunction = """window.getAbsoluteXpath =function(el){
// initialize the variables
aPath ="";
// iterate until the tag name is 'HTML'
while (el.tagName!='HTML'){
// get parent node
pEle=el.parentNode;
// check if there are more than 1 nodes with the same tagname under the parent
if(pEle.querySelectorAll(el.tagName).length>1){
//now findout the index of the current child
cIndex = 0;
pEle.querySelectorAll(el.tagName).forEach(function(cEle){
cIndex= cIndex+1;
// check if iterating ChildNode is equal to current ChildNode
if(cEle === el){
// set the aPath using index
aPath = el.tagName + "[" + cIndex + "]" + "/" +aPath;
}
})
}else{
// simply add the tagName when there is only one child with the tag name
aPath = el.tagName + "/" +aPath;
}
// set parent node as current element
el=el.parentNode;
}
// append HTML to the absolute xpath generated
return "//HTML/"+aPath.substring(0,aPath.length-1);
};"""
Now you can call this method in your javascript and pass element that you are interested in getting the absolute xpath.
Let's try to get the absolute xpath of in stackoverflow.
Note: Did not tested the below code logic due to lack of environment on my machine.
# run the javascript in browser so that you can call the function anytime in your script
remDr %>% executeScript(jsFunction, args = list())
# get stackoverflow `Achievements` link element
webElem <- remDr %>% findElement("css", "a.-link.js-achievements-button")
# # get the absolute xpath of Stackoverflow `Achievements`
remDr %>% executeScript("return getAbsoluteXpath(arguments[0])", args = list(webElem))
Screenshot: Ran the javascript in chrome browser console for evidence
Upvotes: 2