When I use querySelectorAll, I can find 138 td nodes in my sample document.
Array.from(document.querySelectorAll('td')).length
138
When I do the same with XPath, I get no result:
Array.from(document.evaluate(".//td", document.body, null, XPathResult.ANY_TYPE, null)).length
0
Although there is at least one match:
document.evaluate(".//td", document.body, null, XPathResult.ANY_TYPE, null).iterateNext().nodeName
"TD"
The problem seems to be that Array.from can not iterate over a XPathResult. Even this returns 0:
Array.from(document.evaluate('.', document.body, null, XPathResult.ANY_TYPE, null)).length
0
How to make a XPathResult suitable for Array.from?
Unfortunately you can't. Array.from can convert two types of objects into arrays:
.length property.XPathResult doesn't do any of these. You could do this by manually iterating over the result and storing the results in an array such as:
const nodes = [];
let node;
while ((node = xPathResult.iterateNext())) {
nodes.push(node);
}
...but if you're going to loop over the nodes anyway, you can probably do whatever array operations you wanted to do in the loop.
Building up on the answer from @JamesTheAwesomeDude, you can use Array.from (or the spread operator) if you polyfill the iterator onto XPathResult. This iterator is just a bit better because it can operate on all types of XPathResult:
if (!XPathResult.prototype[Symbol.iterator]) XPathResult.prototype[Symbol.iterator] = function* () {
switch (this.resultType) {
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
let result;
while ( (result = this.iterateNext()) != null ) yield result;
break;
case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
for (let i=0; i < this.snapshotLength; i++) yield this.snapshotItem(i);
break;
default:
yield this.singleNodeValue;
break;
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With