Developer tools have nice helpers – $x (Firefox) and $x (Chrome) – but DOM interface is archaic:
nodes = document.evaluate('(//text())[last()]', document) // XPathResult for (let node of nodes) {} Uncaught TypeError: nodes is not iterable [...nodes] Uncaught TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
Bring it to modern era with iterator:
XPathResult.prototype[Symbol.iterator] = function *() { let next; while (next = this.iterateNext()) { yield next; } } for (let node of nodes) {} [...nodes].forEach
Align with query selector API:
document.propertyOwner('querySelectorAll') // Document {…} document.documentElement.propertyOwner('querySelectorAll') // Element {…} Document.prototype.queryXPathAll = function(expression, ...args) { return [...this.evaluate(expression, this, args)] } Element.prototype.queryXPathAll = function(expression, ...args) { return [...this.ownerDocument.evaluate(expression, this, args)] }
(Document.prototype
has a separate function because document.ownerDocument !== document
)