The returned variable xpathResult
from document.evaluate
can either be composed of individual nodes (simple types), or a collection of nodes (node-set types).
Simple Types
When the desired result type in resultType
is specified as either:
-
NUMBER_TYPE
- a double -
STRING_TYPE
- a string -
BOOLEAN_TYPE
- a boolean
We obtain the returned value of the expression by accessing the following properties respectively of the XPathResult
object.
numberValue
stringValue
booleanValue
Example
The following uses the XPath expression count(//p)
to obtain the number of <p>
elements in an HTML document:
const paragraphCount = document.evaluate('count(//p)', document, null, XPathResult.ANY_TYPE, null);
console.log(`This document contains ${paragraphCount.numberValue} paragraph elements.`);
Although JavaScript allows us to convert the number to a string for display, the XPath interface will not automatically convert the numerical result if the stringValue
property is requested, so the following code will not work:
const paragraphCount = document.evaluate('count(//p)', document, null, XPathResult.ANY_TYPE, null);
console.log(`This document contains ${paragraphCount.stringValue} paragraph elements.`);
Instead, it will return an exception with the code NS_DOM_TYPE_ERROR
.
Node-Set Types
The XPathResult
object allows node-sets to be returned in 3 principal different types:
Iterators
When the specified result type in the resultType
parameter is either:
UNORDERED_NODE_ITERATOR_TYPE
ORDERED_NODE_ITERATOR_TYPE
The XPathResult
object returned is a node-set of matched nodes which will behave as an iterator, allowing us to access the individual nodes contained by using the iterateNext()
method of the XPathResult
.
Once we have iterated over all of the individual matched nodes, iterateNext()
will return null
.
Note however, that if the document is mutated (the document tree is modified) between iterations that will invalidate the iteration and the invalidIteratorState
property of XPathResult
is set to true
, and a NS_ERROR_DOM_INVALID_STATE_ERR
exception is thrown.
const iterator = document.evaluate('//phoneNumber', documentNode, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
try {
let thisNode = iterator.iterateNext();
while (thisNode) {
console.log(thisNode.textContent);
thisNode = iterator.iterateNext();
}
}
catch(e) {
console.error(`Error: Document tree modified during iteration ${e}`);
}
Snapshots
When the specified result type in the resultType
parameter is either:
UNORDERED_NODE_SNAPSHOT_TYPE
ORDERED_NODE_SNAPSHOT_TYPE
The XPathResult
object returned is a static node-set of matched nodes, which allows us to access each node through the snapshotItem(itemNumber)
method of the XPathResult
object, where itemNumber
is the index of the node to be retrieved. The total number of nodes contained can be accessed through the snapshotLength
property.
Snapshots do not change with document mutations, so unlike the iterators, the snapshot does not become invalid, but it may not correspond to the current document, for example, the nodes may have been moved, it might contain nodes that no longer exist, or new nodes could have been added.
const nodesSnapshot = document.evaluate('//phoneNumber', documentNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i=0; i < nodesSnapshot.snapshotLength; i++)
{
console.log(nodesSnapshot.snapshotItem(i).textContent);
}
First Node
When the specified result type in the resultType
parameter is either:
ANY_UNORDERED_NODE_TYPE
FIRST_ORDERED_NODE_TYPE
The XPathResult
object returned is only the first found node that matched the XPath expression. This can be accessed through the singleNodeValue
property of the XPathResult
object. This will be null
if the node set is empty.
Note that, for the unordered subtype the single node returned might not be the first in document order, but for the ordered subtype you are guaranteed to get the first matched node in the document order.
const firstPhoneNumber = document.evaluate('//phoneNumber', documentNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
console.log(`The first phone number found is ${firstPhoneNumber.singleNodeValue.textContent}`);
The ANY_TYPE Constant
When the result type in the resultType
parameter is specified as ANY_TYPE
, the XPathResult
object returned, will be whatever type that naturally results from the evaluation of the expression.
It could be any of the simple types (NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE
), but, if the returned result type is a node-set then it will only be an UNORDERED_NODE_ITERATOR_TYPE
.
To determine that type after evaluation, we use the resultType
property of the XPathResult
object. The constant values of this property are defined in the appendix. None Yet =====Any_Type Example===== <pre> </pre>