Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript get XPath of a node

Is there anyway to return an XPath string of a DOM element in Javascript?

like image 458
Louis Avatar asked Apr 18 '10 09:04

Louis


People also ask

Can you use XPath 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.

What is a node in XPath?

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.

How do I navigate to parent node in XPath?

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.


2 Answers

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;  }  
like image 56
stijn de ryck Avatar answered Sep 21 '22 13:09

stijn de ryck


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.

like image 36
bobince Avatar answered Sep 22 '22 13:09

bobince