The following custom utility function can be used to evaluate XPath expressions on given XML nodes. The first argument is a DOM node or Document object, while the second is a string defining an XPath expression.
Example: Defining a custom node-specific evaluateXPath()
utility function
function evaluateXPath(aNode, aExpr) {
const xpe = new XPathEvaluator();
const nsResolver = xpe.createNSResolver(aNode.ownerDocument === null ? aNode.documentElement : aNode.ownerDocument.documentElement);
const result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null);
const found = [];
let res;
while (res = result.iterateNext())
found.push(res);
return found;
}
This function uses the new XPathEvaluator()
constructor, which is supported in Firefox, Chrome, Opera and Safari, but not in Edge or Internet Explorer. Scripts in a Web document which might be accessed by Edge or Internet Explorer users should replace the call to new XPathEvaluator()
with the following fragment:
const xpe = aNode.ownerDocument || aNode;
In that case the creation of the XPathNSResolver can be simplified as:
const nsResolver = xpe.createNSResolver(xpe.documentElement);
Note however that createNSResolver
should only be used if you are sure the namespace prefixes in the XPath expression match those in the document you want to query (and that no default namespace is being used (though see document.createNSResolver for a workaround)). Otherwise, you have to provide your own implementation of XPathNSResolver.
If you are using XMLHttpRequest to read a local or remote XML file into a DOM tree (as described in Parsing and serializing XML), the first argument to evaluateXPath()
should be req.responseXML
.
Sample usage
Assume we have the following XML document (see also How to Create a DOM tree and Parsing and serializing XML):
Example: An XML document to use with the custom evaluateXPath()
utility function
<?xml version="1.0"?>
<people>
<person first-name="eric" middle-initial="H" last-name="jung">
<address street="321 south st" city="denver" state="co" country="usa"/>
<address street="123 main st" city="arlington" state="ma" country="usa"/>
</person>
<person first-name="jed" last-name="brown">
<address street="321 north st" city="atlanta" state="ga" country="usa"/>
<address street="123 west st" city="seattle" state="wa" country="usa"/>
<address street="321 south avenue" city="denver" state="co" country="usa"/>
</person>
</people>
You can now "query" the document with XPath expressions. Although walking the DOM tree can achieve similar results, using XPath expressions is much quicker and more powerful. If you can rely on id
attributes, document.getElementById()
is still powerful, but it's not nearly as powerful as XPath. Here are some examples.
Example: JavaScript code with the custom evaluateXPath()
utility function
let results = evaluateXPath(people, "//person/@last-name");
for (const i in results)
console.log(`Person #${i} has the last name ${results[i].value}`);
results = evaluateXPath(people, "/people/person[2]");
results = evaluateXPath(people, "//person[address/@city='denver']");
results = evaluateXPath(people, "//address[contains(@street, 'south')]");
console.log(results.length);