Skip to content

Instantly share code, notes, and snippets.

@iimos
Last active June 24, 2024 17:05
Show Gist options
  • Save iimos/e9e96f036a3c174d0bf4 to your computer and use it in GitHub Desktop.
Save iimos/e9e96f036a3c174d0bf4 to your computer and use it in GitHub Desktop.
Micro function that gives xpath by element and elements by xpath.
function xpath(el) {
if (typeof el == "string") return document.evaluate(el, document, null, 0, null)
if (!el || el.nodeType != 1) return ''
if (el.id) return "//*[@id='" + el.id + "']"
var sames = [].filter.call(el.parentNode.children, function (x) { return x.tagName == el.tagName })
return xpath(el.parentNode) + '/' + el.tagName.toLowerCase() + (sames.length > 1 ? '['+([].indexOf.call(sames, el)+1)+']' : '')
}
// Usage:
// Getting xpath for node:
var xp = xpath(elementNode)
// Executing xpath:
var iterator = xpath("//h2")
var el = iterator.iterateNext();
while (el) {
// work with element...
el = iterator.iterateNext();
}
@kindziora
Copy link

nice !

@ogarciacapetillo
Copy link

Need help to implement your function, after injecting the js on the browser this is my result,

XpathResult { resultType:4, invalidIteratorState: false}

@iimos
Copy link
Author

iimos commented Jan 20, 2017

@ogarciacapetillo I have added the usage examples. Sorry for the delayed response, i have not recieved any notifications.

@gqqnbig
Copy link

gqqnbig commented Dec 20, 2017

The code doesn't work in IE 11.

When el is HTMLHtmlElement, el.parentNode.children is undefined, thus line 5 throws exception.

My suggestion is to change the bottom part to

if (el.parentNode.nodeType === 1)
{
    var sames = [].filter.call(el.parentNode.children, function(x) { return x.tagName === el.tagName });
    return getSelector(el.parentNode) + '/' + el.tagName.toLowerCase() + (sames.length > 1 ? '[' + (sames.indexOf(el) + 1) + ']' : '');
} else
    return el.tagName.toLowerCase();

@adelriosantiago
Copy link

adelriosantiago commented Jan 14, 2020

Why is the iterator needed? Shouldn't the function always lead to a single element?

BTW, thanks for this amazing piece of cake! It is working good so far.

@brettsprads
Copy link

Works great! Thank you so much

ps: as xpath isn't truly unique, got any thoughts on making it unique?
I'm thinking something like... combining xpath + href + css selectors to make a unique generated ID etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment