How to Calculate the Xpath Position of an Element Using JavaScript

How to calculate the XPath position of an element using Javascript?

Firebug can do this, and it's open source (BSD) so you can reuse their implementation, which does not require any libraries.

3rd party edit

This is an extract from the linked source above. Just in case the link above will change. Please check the source to benefit from changes and updates or the full featureset provided.

Xpath.getElementXPath = function(element)
{
if (element && element.id)
return '//*[@id="' + element.id + '"]';
else
return Xpath.getElementTreeXPath(element);
};

Above code calls this function.
Attention i added some line-wrapping to avoid horizontal scroll bar

Xpath.getElementTreeXPath = function(element)
{
var paths = []; // Use nodeName (instead of localName)
// so namespace prefix is included (if any).
for (; element && element.nodeType == Node.ELEMENT_NODE;
element = element.parentNode)
{
var index = 0;
var hasFollowingSiblings = false;
for (var sibling = element.previousSibling; sibling;
sibling = sibling.previousSibling)
{
// Ignore document type declaration.
if (sibling.nodeType == Node.DOCUMENT_TYPE_NODE)
continue;

if (sibling.nodeName == element.nodeName)
++index;
}

for (var sibling = element.nextSibling;
sibling && !hasFollowingSiblings;
sibling = sibling.nextSibling)
{
if (sibling.nodeName == element.nodeName)
hasFollowingSiblings = true;
}

var tagName = (element.prefix ? element.prefix + ":" : "")
+ element.localName;
var pathIndex = (index || hasFollowingSiblings ? "["
+ (index + 1) + "]" : "");
paths.splice(0, 0, tagName + pathIndex);
}

return paths.length ? "/" + paths.join("/") : null;
};

Javascript get XPath of a node

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.

How do i get the xpath of an element in an X/HTML file

You can extract this functionality from an XPath tool I once wrote:

http://webkitchen.cz/lab/opera/xpath-tool/xpath-tool.js


Edit: here you go:

function getXPath(node) {
var comp, comps = [];
var parent = null;
var xpath = '';
var getPos = function(node) {
var position = 1, curNode;
if (node.nodeType == Node.ATTRIBUTE_NODE) {
return null;
}
for (curNode = node.previousSibling; curNode; curNode = curNode.previousSibling) {
if (curNode.nodeName == node.nodeName) {
++position;
}
}
return position;
}

if (node instanceof Document) {
return '/';
}

for (; node && !(node instanceof Document); node = node.nodeType == Node.ATTRIBUTE_NODE ? node.ownerElement : node.parentNode) {
comp = comps[comps.length] = {};
switch (node.nodeType) {
case Node.TEXT_NODE:
comp.name = 'text()';
break;
case Node.ATTRIBUTE_NODE:
comp.name = '@' + node.nodeName;
break;
case Node.PROCESSING_INSTRUCTION_NODE:
comp.name = 'processing-instruction()';
break;
case Node.COMMENT_NODE:
comp.name = 'comment()';
break;
case Node.ELEMENT_NODE:
comp.name = node.nodeName;
break;
}
comp.position = getPos(node);
}

for (var i = comps.length - 1; i >= 0; i--) {
comp = comps[i];
xpath += '/' + comp.name;
if (comp.position != null) {
xpath += '[' + comp.position + ']';
}
}

return xpath;

}

It might need some changes if you want it to work in IE as well.

Find specific element position in XPath after checking a condition

This is one possible way : (formatted for readability)

//table[@class='detailTable']
//tr
/td[*[contains(.,'Statement Date')]]
/following-sibling::td[1]
/*[position()
=
count(
parent::td
/preceding-sibling::td[1]
/*[contains(.,'Statement Date')]/preceding-sibling::*
)+1
]

explanation :

  • ..../td[*[contains(.,'Statement Date')]] : From the beginning up to this part, the XPath will find td element where, at least, one of its children contains text "Statement Date"
  • /following-sibling::td[1] : from previously matched td, navigate to the nearest following sibling td ...
  • /*[position() = count(parent::td/preceding-sibling::td[1]/*[contains(.,'Statement Date')]/preceding-sibling::*)+1] : ...and return child element at position equals to position of element that contains text "Statement Date" in the previous td. Notice that we use count(preceding-sibling::*)+1 to get position index of the element containing text "Statement Date" here.

Get element's xpath in javascript

There are many ways howto access an element with XPath. For example you can access it by node name or by the value of one of it's attributes or child nodes. So you can not expect that javascript gives you exactly one of them.

But as you have the id, the simplest xpath query to access the element would be:

//*[@id="THE_ID"]

How to create a Xpath of the clicked element using Javascript or Jquery?

You need to loop through clicked element and it parents to do this work. So you can call a function nesting to do this work.

var xpath;$("*").click(function(e){  xpath = '';  addXpath($(this));  console.log(xpath);  e.stopPropagation();});
function addXpath($ele){ var tagName = $ele[0].tagName.toLowerCase(); var index = $ele.parent().children(tagName).index($ele)+1; xpath = '/'+tagName +'['+index+']'+ xpath; !$ele.parent().is(document) ? addXpath($ele.parent()) : "";}
body {background: green}.header {background: orange}.row_in {background: yellow}.row_in_in {background: blue}span {background: red}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="header">Countries</div><div class="row"><div class="row_in">  <div class="row_in_in">    <span>India</span>  </div></div></div><div class="row"><div class="row_in">  <div class="row_in_in">    <span>USA</span>  </div></div></div><div class="row"><div class="row_in">  <div class="row_in_in">    <span>UK</span>  </div></div></div><div class="row"><div class="row_in">  <div class="row_in_in">    <span>France</span>  </div></div></div>

How to use xpath in JavaScript?

It would do what you want:

function xpathFindById(id) {
return document.evaluate(".//*[@id='" + id + "']", document.lastChild, null,
XPathResult.ANY_TYPE, null).iterateNext();
}

var content = xpathFindById("content");

Finding an element in another element by Xpath

You missed . at the heading of following xpath, . at here means search element start from current node which is the parent node. Without . at here your xpath tells browser to search element start from the beginning of the HTML.

card.element(by.xpath('.//ep-check-box[.//span[text()="'+label+'"]]'));



Related Topics



Leave a reply



Submit