I\'m using the document.evaluate()
JavaScript method to get an element pointed to by an XPath expression:
var element = document.evaluate(
pat
I found the following solution in the book I am currently reading. It says that the code is from the Prototype library.
function getElementsByXPath(xpath, parent)
{
let results = [];
let query = document.evaluate(xpath, parent || document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i = 0, length = query.snapshotLength; i < length; ++i) {
results.push(query.snapshotItem(i));
}
return results;
}
Use it like this:
let items = getElementsByXPath("//*"); // return all elements on the page
Try this:
function getListOfElementsByXPath(xpath) {
var result = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
return result;
}
Then call it:
var results = getListOfElementsByXPath("//YOUR_XPATH");
while (node = results.iterateNext()) {
console.log(node);
}
I was working hard with the same problem some weeks ago. I found out, that the result already represents a list of elements (if any) and one can iterate trough it. I needed to build a jQuery plugin for realize a search of partial or full text strings, which means the inner text of any DOM element like LI or H2. I got the initial understanding on his page : Document.evaluate() | MDN
After some hours I got the plugin running: Search for the word "architecture" only in "p" elements, find partial matching strings ("true" for <p>todays architecture in Europe</p>
) instead of matches of entire text (<h2>architecture</h2>
).
var found = $('div#pagecontent').findtext('architecture','p',true);
Found results are regular jQuery objects, which can be used as usual.
found.css({ backgroundColor: 'tomato'});
The example of usage above may be altered like this for search trough entire document and all node types like this (partial results)
var found = $('body').findtext('architecture','',true);
or only exact matches
var found = $('div#pagecontent').findtext('architecture');
The plugin itself shows a variable "es" which is the plural of a single "e" for "element". And you can see, how the results are iterated, and collected into a bunch of objects with f = f.add($(e))
(where "f" stands for "found"). The beginning of the function deals with different conditions, like full or partial search ("c" for condition) and the document range for the search ("d").
It may be optimized whereever needed, may not represent the maximum of possibilities, but it represents my best knowledge at the moment, is running without errors and it may answer your question, hopefully. And here is it:
(function($) {
$.fn.findtext = function(s,t,p) {
var c, d;
if (!this[0]) d = document.body;
else d = this[0];
if (!t || typeof t !== 'string' || t == '') t = '*';
if (p === true) c = './/'+t+'[contains(text(), "'+s+'")]';
else c = './/'+t+'[. = "'+s+'"]';
var es = document.evaluate(c, d, null, XPathResult.ANY_TYPE, null);
var e = es.iterateNext();
var f = false;
while (e) {
if (!f) f = $(e);
else f = f.add($(e));
e = es.iterateNext();
}
return f || $();
};
})(jQuery);
From the documentation
var iterator = document.evaluate('//phoneNumber', documentNode, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );
try {
var thisNode = iterator.iterateNext();
while (thisNode) {
alert( thisNode.textContent );
thisNode = iterator.iterateNext();
}
}
catch (e) {
dump( 'Error: Document tree modified during iteration ' + e );
}