Method 1

Using XPathEvaluator with start node and multiple results.
source

function evaluateXPath(aNode, aExpr) {
var xpe = new XPathEvaluator();
var nsResolver = xpe.createNSResolver(aNode.ownerDocument == null ?
aNode.documentElement : aNode.ownerDocument.documentElement);
var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null);
var found = [];
var res;
while (res = result.iterateNext())
found.push(res);
return found;
}

Sample query:

evaluateXPath(document, '//button[@title="Edit" or @title="Add"]')

/* Result:
[button#49431283ecf54dbaba1fcd8bf735af41.WABN.WEBN.WIMO.WNTN.WO5M]
0: button#49431283ecf54dbaba1fcd8bf735af41.WABN.WEBN.WIMO.WNTN.WO5M
length: 1
__proto__: Array(0)
/*

Method 2

Single node, always against document using XPathEvaluator
source

function getElementByXPath(xpath) {
return new XPathEvaluator()
.createExpression(xpath)
.evaluate(document, XPathResult.FIRST_ORDERED_NODE_TYPE)
.singleNodeValue
}

console.log( getElementByXPath("//html[1]/body[1]/div[1]") );

Method 3

Single node, against document using document.evaluate

function getElementByXpath(path) {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}

console.log( getElementByXpath("//html[1]/body[1]/div[1]") );function getElementByXpath(path) {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}

console.log( getElementByXpath("//html[1]/body[1]/div[1]") );