Is there anyway to return an XPath string of a DOM element in Javascript?
This document describes the interface for using XPath in JavaScript internally, in extensions, and from websites. Mozilla implements a fair amount of the DOM 3 XPath, which means that XPath expressions can be run against both HTML and XML documents.
In XPath, there are seven kinds of nodes: element, attribute, text, namespace, processing-instruction, comment, and document nodes. XML documents are treated as trees of nodes. The topmost element of the tree is called the root element.
A Parent of a context node is selected Flat element. A string of elements is normally separated by a slash in an XPath statement. You can pick the parent element by inserting two periods “..” where an element would typically be. The parent of the element to the left of the double period will be selected.
I refactored this from another example. It will attempt to check or there is for sure a unique id and if so use that case to shorten the expression.
function createXPathFromElement(elm) { var allNodes = document.getElementsByTagName('*'); for (var segs = []; elm && elm.nodeType == 1; elm = elm.parentNode) { if (elm.hasAttribute('id')) { var uniqueIdCount = 0; for (var n=0;n < allNodes.length;n++) { if (allNodes[n].hasAttribute('id') && allNodes[n].id == elm.id) uniqueIdCount++; if (uniqueIdCount > 1) break; }; if ( uniqueIdCount == 1) { segs.unshift('id("' + elm.getAttribute('id') + '")'); return segs.join('/'); } else { segs.unshift(elm.localName.toLowerCase() + '[@id="' + elm.getAttribute('id') + '"]'); } } else if (elm.hasAttribute('class')) { segs.unshift(elm.localName.toLowerCase() + '[@class="' + elm.getAttribute('class') + '"]'); } else { for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) { if (sib.localName == elm.localName) i++; }; segs.unshift(elm.localName.toLowerCase() + '[' + i + ']'); }; }; return segs.length ? '/' + segs.join('/') : null; }; function lookupElementByXPath(path) { var evaluator = new XPathEvaluator(); var result = evaluator.evaluate(path, document.documentElement, null,XPathResult.FIRST_ORDERED_NODE_TYPE, null); return result.singleNodeValue; }
There's not a unique XPath to a node, so you'll have to decide what's the most appropriate way of constructing a path. Use IDs where available? Numeral position in the document? Position relative to other elements?
See getPathTo()
in this answer for one possible approach.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With