Introduction to using XPath in JavaScript

  • Revision slug: Introduction_to_using_XPath_in_JavaScript
  • Revision title: Introduction to using XPath in JavaScript
  • Revision id: 110872
  • Created:
  • Creator: Fredchat
  • Is current revision? No
  • Comment /* Implementing a default namespace for XML documents - punctuation */

Revision Content

This document describes the interface for using XPath in JavaScript internally, in extensions, and from websites. Mozilla implements a fair amount of the DOM 3 XPath. Which means that XPath expressions can be run against both HTML and XML documents.

The main interface to using XPath is the evaluate function of the document object.

document.evaluate

This method evaluates XPath expressions against a XML based document (including HTML documents), and returns a XPathResult object, which can be a single node or a set of nodes. The existing documentation for this method is located at DOM:document.evaluate but it is rather sparse for our needs at the moment, a more comprehensive examination will be given below.

var xpathResult = document.evaluate( xpathExpression, contextNode, namespaceResolver, resultType, result );

Parameters

The evaluate function takes a total of five parameters:

  • xpathExpression: A string containing the XPath expression to be evaluated.
  • contextNode: A node in the document against which the xpathExpression should be evaluated, including any and all of its child nodes. The document node is the most commonly used.
  • namespaceResolver: A function that will be passed any namespace prefixes contained within xpathExpression which returns a string representing the namespace URI associated with that prefix. This enables conversion between the prefixes used in the XPath expressions and the possibly different prefixes used in the document. The function can be either:
    • Created by using the createNSResolver method of a XPathEvaluator object. You should use this virtually all of the time.
    • null, which can be used for HTML documents or when no namespace prefixes are used. Note that if the xpathExpression contains a namespace prefix this will result in a DOMException being thrown with the code NAMESPACE_ERR.
    • A custom user-defined function. See the Using a User Defined Namespace Resolver section in the appendix for details.
  • resultType: A constant that specifies the desired result type to be returned as a result of the evaluation. The most commonly passed constant is XPathResult.ANY_TYPE which will return the results of the XPath expression as the most natural type. There is a section in the appendix which contains a full list of the available constants. They are explained in the Specifying the Return Type section below.
  • result: Either an existing XPathResult object which is to be reused to return the results, or null can be used which creates a new XPathResult object.

Return Value

Returns xpathResult, which is a XPathResult object of the type specified in the resultType parameter. The XPathResult Interface is defined here.

Implementing a Default Namespace Resolver

We create a namespace resolver using the createNSResolver method of the document object.

var nsResolver = document.createNSResolver( contextNode.ownerDocument == null ? contextNode.documentElement : contextNode.ownerDocument.documentElement );

Or alternatively by using the <code>createNSResolver</code> method of a <code>XPathEvaluator</code> object. <pre> var xpEvaluator = new XPathEvaluator(); var nsResolver = xpEvaluator.createNSResolver( contextNode.ownerDocument == null ? contextNode.documentElement : contextNode.ownerDocument.documentElement ); </pre> And then pass document.evaluate, the nsResolver variable as the namespaceResolver parameter.

Note, XPath defines QNames without prefix to match only elements in the null namespace. There is no way in XPath to pick up the default namespace. To match elements or attributes in a non-null namespace, you have to use prefixed name tests, and create namespace resolver mapping the prefix to the namespace. Read more on how to create a user defined namespace resolver below.

Specifying the Return Type

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 a HTML document:

var paragraphCount = document.evaluate( 'count(//p)', document, null, XPathResult.ANY_TYPE, null );

alert( '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 '<big>not</big>' work:

var paragraphCount = document.evaluate('count(//p)', document, null, XPathResult.ANY_TYPE, null );

alert( '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.

Iterator Example
var iterator = document.evaluate('//phoneNumber', documentNode, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );

try {
  var thisNode = iterator.iterateNext();
  
  while (thisNode) {
    alert( thisNode.textContent );
    thisNode = iterator.iterateNext();
  }	
}
catch (e) {
  dump( 'Error: Document tree modified during iteraton ' + 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.

Snapshot Example
var nodesSnapshot = document.evaluate('//phoneNumber', documentNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );

for ( var i=0 ; i < nodesSnapshot.snapshotLength; i++ )
{
  dump( 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.

First Node Example
var firstPhoneNumber = document.evaluate('//phoneNumber', documentNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null );

dump( '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 ), <big>but</big>, if the returned result type is a node-set then it will <big>only</big> 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>

Examples

Within a HTML Document

The following code is intended to be placed in any JavaScript fragment within or linked to the HTML document that the XPath expression is to be evaluated against.

To extract all the <h2> heading elements in a HTML document using XPath, the xpathExpression is simply '//h2'. Where, // is the Recursive Descent Operator that matches elements with the nodeName h2 anywhere in the document tree. The full code for this is: link to introductory xpath doc

var headings = document.evaluate('//h2', document, null, XPathResult.ANY_TYPE, null );

Notice that, since HTML does not have namespaces, we have passed null for the namespaceResolver parameter.

Since we wish to search over the entire document for the headings, we have used the document object itself as the contextNode.

The result of this expression is an XPathResult object. If we wish to know the type of result returned, we may evaluate the resultType property of the returned object. In this case that will evaluate to 4, a UNORDERED_NODE_ITERATOR_TYPE. This is the default return type when the result of the XPath expression is a node-set. It provides access to a single node at a time and may not return nodes in a particular order. To access the returned nodes, we use the iterateNext() method of the returned object:

var thisHeading = headings.iterateNext();

var alertText = 'Level 2 headings in this document are:\n'

while (thisHeading) {
  alertText += thisHeading.textContent + '\n';
  thisHeading = headings.iterateNext();
}

Once we iterate to a node, we have access to all the standard DOM interfaces on that node. After iterating through all the h2 elements returned from our expression, any further calls to iterateNext() will return null.

Evaluating against an XML document within an Extension

The following uses an XML document located at chrome://yourextension/content/peopleDB.xml as an example.

<?xml version="1.0"?>
<people xmlns:xul = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >
  <person>
	<name first="george" last="bush" />
	<address street="1600 pennsylvania avenue" city="washington" country="usa"/>
	<phoneNumber>202-456-1111</phoneNumber>
  </person>
  <person>
	<name first="tony" last="blair" />
	<address street="10 downing street" city="london" country="uk"/>
	<phoneNumber>020 7925 0918</phoneNumber>
  </person>
</people>

To make the contents of the XML document available within the extension, we create a XMLHttpRequest object to load the document synchronously, the variable xmlDoc will contain the document as an XMLDocument object against which we can use the evaluate method

JavaScript used in the extensions xul/js documents.

var req = new XMLHttpRequest();

req.open("GET", "chrome://yourextension/content/peopleDB.xml", false); 
req.send(null);

var xmlDoc = req.responseXML;		

var nsResolver = xmlDoc.createNSResolver( xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement);

var personIterator = xmlDoc.evaluate('//person', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null );

Appendix

Implementing a User Defined Namespace Resolver

This is an example for illustration only. This function will need to take namespace prefixes from the xpathExpression and return the URI that corresponds to that prefix. For example, the expression:

'//xhtml:td/mathml:math'

will select all MathML expressions that are the children of (X)HTML table data cell elements.

In order to associate the mathml: prefix with the namespace URI 'http://www.w3.org/1998/Math/MathML' and html: with the URI http://www.w3.org/1999/xhtml we provide a function:

function nsResolver(prefix) {
  var ns = {
    'xhtml' : 'http://www.w3.org/1999/xhtml',
    'mathml': 'http://www.w3.org/1998/Math/MathML'
  };
  return ns[prefix] || null;
}

Our call to document.evaluate would then looks like:

document.evaluate( '//xhtml:td/mathml:math', document, nsResolver, XPathResult.ANY_TYPE, null );

Implementing a default namespace for XML documents

As noted in the #Implementing a Default Namespace Resolver previously, the default resolver does not handle the default namespace for XML documents. For example with this document:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <entry />
    <entry />
    <entry />
</feed>

doc.evaluate('//entry', doc, nsResolver, XPathResult.ANY_TYPE, null) will return an empty set, where nsResolver is the resolver returned by createNSResolver. Passing a null resolver doesn't work any better, either.

One possible workaround is to create a custom resolver that returns the correct default namespace (the Atom namespace in this case). E.g.:

function resolver() {
    return 'http://www.w3.org/2005/Atom';
}
doc.evaluate('//entry', doc, resolver, XPathResult.ANY_TYPE, null)

Note that a more complex resolver will be required if the document uses multiple namespaces.

XPathResult Defined Constants

Result Type Defined Constant Value Description
ANY_TYPE 0 A result set containing whatever type naturally results from evaluation of the expression. Note that if the result is a node-set then UNORDERED_NODE_ITERATOR_TYPE is always the resulting type.
NUMBER_TYPE 1 A result containing a single number. This is useful for example, in an XPath expression using the count() function.
STRING_TYPE 2 A result containing a single string.
BOOLEAN_TYPE 3 A result containing a single boolean value. This is useful for example, in an XPath expression using the not() function.
UNORDERED_NODE_ITERATOR_TYPE 4 A result node-set containing all the nodes matching the expression. The nodes may not necessarily be in the same order that they appear in the document.
ORDERED_NODE_ITERATOR_TYPE 5 A result node-set containing all the nodes matching the expression. The nodes in the result set are in the same order that they appear in the document.
UNORDERED_NODE_SNAPSHOT_TYPE 6 A result node-set containing snapshots of all the nodes matching the expression. The nodes may not necessarily be in the same order that they appear in the document.
ORDERED_NODE_SNAPSHOT_TYPE 7 A result node-set containing snapshots of all the nodes matching the expression. The nodes in the result set are in the same order that they appear in the document.
ANY_UNORDERED_NODE_TYPE 8 A result node-set containing any single node that matches the expression. The node is not necessarily the first node in the document that matches the expression.
FIRST_ORDERED_NODE_TYPE 9 A result node-set containing the first node in the document that matches the expression.

Original Document Information

  • Based Upon Original Document Mozilla XPath Tutorial
  • Original Source Author: James Graham.
  • Other Contributors: James Thompson.
  • Last Updated Date: 2006-3-25.
{{ wiki.languages( { "ja": "ja/Introduction_to_using_XPath_in_JavaScript", "ko": "ko/Introduction_to_using_XPath_in_JavaScript" } ) }}

Revision Source

<p>
</p><p>This document describes the interface for using <a href="en/XPath">XPath</a> in JavaScript internally, in extensions, and from websites. Mozilla implements a fair amount of the <a class="external" href="http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html">DOM 3 XPath</a>. Which means that XPath expressions can be run against both HTML and XML documents.
</p><p>The main interface to using XPath is the <a href="en/DOM/document.evaluate">evaluate</a> function of the <a href="en/DOM/document">document</a> object.
</p>
<h2 name="document.evaluate">document.evaluate</h2>
<p>This method evaluates <a href="en/XPath">XPath</a> expressions against a <a href="en/XML">XML</a> based document (including HTML documents), and returns a <code>XPathResult</code> object, which can be a single node or a set of nodes. The existing documentation for this method is located at <a href="en/DOM/document.evaluate">DOM:document.evaluate</a> but it is rather sparse for our needs at the moment, a more comprehensive examination will be given below.
</p>
<pre>var xpathResult = document.evaluate( xpathExpression, contextNode, namespaceResolver, resultType, result );
</pre>
<h3 name="Parameters">Parameters</h3>
<p>The <a href="en/DOM/document.evaluate">evaluate</a> function takes a total of five parameters:
</p>
<ul><li> <code>xpathExpression</code>: A string containing the XPath expression to be evaluated.
</li></ul>
<ul><li> <code>contextNode</code>: A node in the document against which the <code>xpathExpression</code> should be evaluated, including any and all of its child nodes. The <a href="en/DOM/document">document</a> node is the most commonly used.
</li></ul>
<ul><li> <code>namespaceResolver</code>: A function that will be passed any namespace prefixes contained within <code>xpathExpression</code> which returns a string representing the namespace URI associated with that prefix. This enables conversion between the prefixes used in the XPath expressions and the possibly different prefixes used in the document. The function can be either:
<ul><li> <a href="#Implementing_a_Default_Namespace_Resolver">Created</a> by using the <code><a href="en/DOM/document.createNSResolver">createNSResolver</a></code> method of a <code><a class="external" href="http://www.xulplanet.com/references/objref/XPathEvaluator.html">XPathEvaluator</a></code> object. You should use this virtually all of the time.
</li><li> <code>null</code>, which can be used for HTML documents or when no namespace prefixes are used. Note that if the <code>xpathExpression</code> contains a namespace prefix this will result in a <code>DOMException</code> being thrown with the code <code>NAMESPACE_ERR</code>.
</li><li> A custom user-defined function. See the <a href="#Implementing_a_User_Defined_Namespace_Resolver">Using a User Defined Namespace Resolver</a> section in the appendix for details.
</li></ul>
</li></ul>
<ul><li> <code>resultType</code>: A <a href="#XPathResult_Defined_Constants">constant</a> that specifies the desired result type to be returned as a result of the evaluation. The most commonly passed constant is <code>XPathResult.ANY_TYPE</code> which will return the results of the XPath expression as the most natural type. There is a section in the appendix which contains a full list of the <a href="#XPathResult_Defined_Constants">available constants</a>. They are explained in the <a href="#Specifying_the_Return_Type">Specifying the Return Type</a> section below.
</li></ul>
<ul><li> <code>result</code>: Either an existing <code>XPathResult</code> object which is to be reused to return the results, or <code>null</code> can be used which creates a new <code>XPathResult</code> object.
</li></ul>
<h3 name="Return_Value">Return Value</h3>
<p>Returns <code>xpathResult</code>, which is a <code>XPathResult</code> object of the type <a href="#Specifying_the_Return_Type">specified</a> in the <code>resultType</code> parameter. The <code>XPathResult</code> Interface is defined <a class="external" href="http://lxr.mozilla.org/seamonkey/source/dom/public/idl/xpath/nsIDOMXPathResult.idl">here</a>.
</p>
<h3 name="Implementing_a_Default_Namespace_Resolver">Implementing a Default Namespace Resolver</h3>
<p>We create a namespace resolver using the <code>createNSResolver</code> method of the <a href="en/DOM/document">document</a> object.
</p>
<pre>var nsResolver = document.createNSResolver( contextNode.ownerDocument == null ? contextNode.documentElement : contextNode.ownerDocument.documentElement );
</pre>
<p><span class="comment">Or alternatively by using the &lt;code&gt;createNSResolver&lt;/code&gt; method of a &lt;code&gt;XPathEvaluator&lt;/code&gt; object.  &lt;pre&gt; var xpEvaluator = new XPathEvaluator();  var nsResolver = xpEvaluator.createNSResolver( contextNode.ownerDocument == null ? contextNode.documentElement : contextNode.ownerDocument.documentElement ); &lt;/pre&gt;</span>
And then pass <code>document.evaluate</code>, the <code>nsResolver</code> variable as the <code>namespaceResolver</code> parameter.
</p><p>Note, XPath defines <code>QNames</code> without prefix to match only elements in the null namespace. There is no way in XPath to pick up the default namespace. To match elements or attributes in a non-null namespace, you have to use prefixed name tests, and create namespace resolver mapping the prefix to the namespace. Read more on how to <a href="#Implementing_a_User_Defined_Namespace_Resolver">create a user defined namespace resolver</a> below.
</p>
<h3 name="Specifying_the_Return_Type">Specifying the Return Type</h3>
<p>The returned variable <code>xpathResult</code> from <code>document.evaluate</code> can either be composed of individual nodes (<a href="#Simple_Types">simple types</a>), or a collection of nodes (<a href="#Node-Set_Types">node-set types</a>).
</p>
<h4 name="Simple_Types">Simple Types</h4>
<p>When the desired result type in <code>resultType</code> is specified as either:
</p>
<ul><li> <code>NUMBER_TYPE</code>  - a double
</li><li> <code>STRING_TYPE</code>  - a string
</li><li> <code>BOOLEAN_TYPE</code> - a boolean
</li></ul>
<p>We obtain the returned value of the expression by accessing the following properties respectively of the <code>XPathResult</code> object.
</p>
<ul><li> <code>numberValue</code>
</li><li> <code>stringValue</code>
</li><li> <code>booleanValue</code>
</li></ul>
<h5 name="Example">Example</h5>
<p>The following uses the XPath expression <code><a href="en/XPath/Functions/count">count(//p)</a></code> to obtain the number of <code><span class="plain">&lt;p&gt;</span></code> elements in a HTML document:
</p>
<pre>var paragraphCount = document.evaluate( 'count(//p)', document, null, XPathResult.ANY_TYPE, null );

alert( 'This document contains ' + paragraphCount.numberValue + ' paragraph elements' );
</pre>
<p>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 <code>stringValue</code> property is requested, so the following code will '<b><big>not</big>'</b> work:
</p>
<pre>var paragraphCount = document.evaluate('count(//p)', document, null, XPathResult.ANY_TYPE, null );

alert( 'This document contains ' + paragraphCount.stringValue + ' paragraph elements' );
</pre>
<p>Instead it will return an exception with the code <code>NS_DOM_TYPE_ERROR</code>.
</p>
<h4 name="Node-Set_Types">Node-Set Types</h4>
<p>The <code>XPathResult</code> object allows node-sets to be returned in 3 principal different types:
</p>
<ul><li> <a href="#Iterators">Iterators</a>
</li><li> <a href="#Snapshots">Snapshots</a>
</li><li> <a href="#First_Node">First Nodes</a>
</li></ul>
<h5 name="Iterators">Iterators</h5>
<p>When the specified result type in the <code>resultType</code> parameter is either:
</p>
<ul><li> <code>UNORDERED_NODE_ITERATOR_TYPE</code>
</li><li> <code>ORDERED_NODE_ITERATOR_TYPE</code>
</li></ul>
<p>The <code>XPathResult</code> 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 <code>iterateNext()</code> method of the <code>XPathResult</code>. 
</p><p>Once we have iterated over all of the individual matched nodes, <code>iterateNext()</code> will return <code>null</code>.
</p><p>Note however, that if the document is mutated (the document tree is modified) between iterations that will invalidate the iteration and the <code>invalidIteratorState</code> property of <code>XPathResult</code> is set to <code>true</code>, and a <code>NS_ERROR_DOM_INVALID_STATE_ERR</code> exception is thrown.
</p>
<h6 name="Iterator_Example">Iterator Example</h6>
<pre>var iterator = document.evaluate('//phoneNumber', documentNode, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );

try {
  var thisNode = iterator.iterateNext();
  
  while (thisNode) {
    alert( thisNode.textContent );
    thisNode = iterator.iterateNext();
  }	
}
catch (e) {
  dump( 'Error: Document tree modified during iteraton ' + e );
}
</pre>
<h5 name="Snapshots">Snapshots</h5>
<p>When the specified result type in the <code>resultType</code> parameter is either:
</p>
<ul><li> <code>UNORDERED_NODE_SNAPSHOT_TYPE</code>
</li><li> <code>ORDERED_NODE_SNAPSHOT_TYPE</code>
</li></ul>
<p>The <code>XPathResult</code> object returned is a static node-set of matched nodes, which allows us to access each node through the <code>snapshotItem(itemNumber)</code> method of the <code>XPathResult</code> object, where <code>itemNumber</code> is the index of the node to be retrieved. The total number of nodes contained can be accessed through the <code>snapshotLength</code> property.
</p><p>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.
</p>
<h6 name="Snapshot_Example">Snapshot Example</h6>
<pre>var nodesSnapshot = document.evaluate('//phoneNumber', documentNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );

for ( var i=0 ; i &lt; nodesSnapshot.snapshotLength; i++ )
{
  dump( nodesSnapshot.snapshotItem(i).textContent );
}
</pre>
<h5 name="First_Node">First Node</h5>
<p>When the specified result type in the <code>resultType</code> parameter is either:
</p>
<ul><li> <code>ANY_UNORDERED_NODE_TYPE</code>
</li><li> <code>FIRST_ORDERED_NODE_TYPE</code>
</li></ul>
<p>The <code>XPathResult</code> object returned is only the first found node that matched the XPath expression. This can be accessed through the <code>singleNodeValue</code> property of the <code>XPathResult</code> object. This will be <code>null</code> if the node set is empty.
</p><p>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.
</p>
<h6 name="First_Node_Example">First Node Example</h6>
<pre>var firstPhoneNumber = document.evaluate('//phoneNumber', documentNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null );

dump( 'The first phone number found is ' + firstPhoneNumber.singleNodeValue.textContent );
</pre>
<h4 name="The_ANY_TYPE_Constant">The ANY_TYPE Constant</h4>
<p>When the result type in the <code>resultType</code> parameter is specified as <code>ANY_TYPE</code>, the <code>XPathResult</code> object returned, will be whatever type that naturally results from the evaluation of the expression. 
</p><p>It could be any of the simple types ( <code>NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE</code> ), <b><big>but</big></b>, if the returned result type is a node-set then it will <b><big>only</big></b> be an <code>UNORDERED_NODE_ITERATOR_TYPE</code>.
</p><p>To determine that type after evaluation, we use the <code>resultType</code> property of the <code>XPathResult</code> object. The <a href="#XPathResult_Defined_Constants">constant</a> values of this property are defined in the appendix.
<span class="comment">None Yet =====Any_Type Example===== &lt;pre&gt;  &lt;/pre&gt;</span>
</p>
<h2 name="Examples">Examples</h2>
<h3 name="Within_a_HTML_Document">Within a HTML Document</h3>
<p>The following code is intended to be placed in any JavaScript fragment within or linked to the HTML document that the XPath expression is to be evaluated against.
</p><p>To extract all the <code><span class="plain">&lt;h2&gt;</span></code> heading elements in a HTML document using XPath, the <code>xpathExpression</code> is simply '<code>//h2</code>'. Where, <code>//</code> is the Recursive Descent Operator that matches elements with the nodeName <code>h2</code> anywhere in the document tree. The full code for this is:
<span class="comment">link to introductory xpath doc</span>
</p>
<pre>var headings = document.evaluate('//h2', document, null, XPathResult.ANY_TYPE, null );
</pre>
<p>Notice that, since HTML does not have namespaces, we have passed <code>null</code> for the <code>namespaceResolver</code> parameter. 
</p><p>Since we wish to search over the entire document for the headings, we have used the <a href="en/DOM/document">document</a> object itself as the <code>contextNode</code>.
</p><p>The result of this expression is an <code>XPathResult</code> object. If we wish to know the type of result returned, we may evaluate the <code>resultType</code> property of the returned object. In this case that will evaluate to <code>4</code>, a <code>UNORDERED_NODE_ITERATOR_TYPE</code>. This is the default return type when the result of the XPath expression is a node-set. It provides access to a single node at a time and may not return nodes in a particular order. To access the returned nodes, we use the <code>iterateNext()</code> method of the returned object:
</p>
<pre>var thisHeading = headings.iterateNext();

var alertText = 'Level 2 headings in this document are:\n'

while (thisHeading) {
  alertText += thisHeading.textContent + '\n';
  thisHeading = headings.iterateNext();
}
</pre>
<p>Once we iterate to a node, we have access to all the standard <a href="en/DOM_interfaces">DOM interfaces</a> on that node. After iterating through all the <code>h2</code> elements returned from our expression, any further calls to <code>iterateNext()</code> will return <code>null</code>.
</p>
<h3 name="Evaluating_against_an_XML_document_within_an_Extension">Evaluating against an XML document within an Extension</h3>
<p>The following uses an XML document located at chrome://yourextension/content/peopleDB.xml as an example.
</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;people xmlns:xul = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" &gt;
  &lt;person&gt;
	&lt;name first="george" last="bush" /&gt;
	&lt;address street="1600 pennsylvania avenue" city="washington" country="usa"/&gt;
	&lt;phoneNumber&gt;202-456-1111&lt;/phoneNumber&gt;
  &lt;/person&gt;
  &lt;person&gt;
	&lt;name first="tony" last="blair" /&gt;
	&lt;address street="10 downing street" city="london" country="uk"/&gt;
	&lt;phoneNumber&gt;020 7925 0918&lt;/phoneNumber&gt;
  &lt;/person&gt;
&lt;/people&gt;
</pre>
<p>To make the contents of the XML document available within the extension, we create a <code><a href="en/XMLHttpRequest">XMLHttpRequest</a></code> object to load the document synchronously, the variable <code>xmlDoc</code> will contain the document as an <code><a href="en/XMLDocument">XMLDocument</a></code> object against which we can use the <code>evaluate</code> method
</p><p>JavaScript used in the extensions xul/js documents.
</p>
<pre>var req = new XMLHttpRequest();

req.open("GET", "chrome://yourextension/content/peopleDB.xml", false); 
req.send(null);

var xmlDoc = req.responseXML;		

var nsResolver = xmlDoc.createNSResolver( xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement);

var personIterator = xmlDoc.evaluate('//person', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null );
</pre>
<h2 name="Appendix">Appendix</h2>
<h4 name="Implementing_a_User_Defined_Namespace_Resolver">Implementing a User Defined Namespace Resolver</h4>
<p>This is an example for illustration only. This function will need to take namespace prefixes from the <code>xpathExpression</code> and return the URI that corresponds to that prefix. For example, the expression:
</p>
<pre>'//xhtml:td/mathml:math'
</pre>
<p>will select all <a href="en/MathML">MathML</a> expressions that are the children of (X)HTML table data cell elements. 
</p><p>In order to associate the <code>mathml:</code> prefix with the namespace URI '<code>http://www.w3.org/1998/Math/MathML</code>' and <code>html:</code> with the URI <code>http://www.w3.org/1999/xhtml</code> we provide a function:
</p>
<pre>function nsResolver(prefix) {
  var ns = {
    'xhtml' : 'http://www.w3.org/1999/xhtml',
    'mathml': 'http://www.w3.org/1998/Math/MathML'
  };
  return ns[prefix] || null;
}
</pre>
<p>Our call to <code>document.evaluate</code> would then looks like:
</p>
<pre>document.evaluate( '//xhtml:td/mathml:math', document, nsResolver, XPathResult.ANY_TYPE, null );
</pre>
<h4 name="Implementing_a_default_namespace_for_XML_documents"> Implementing a default namespace for XML documents </h4>
<p>As noted in the <a href="#Implementing_a_Default_Namespace_Resolver">#Implementing a Default Namespace Resolver</a> previously, the default resolver does not handle the default namespace for XML documents.  For example with this document:
</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;feed xmlns="http://www.w3.org/2005/Atom"&gt;
    &lt;entry /&gt;
    &lt;entry /&gt;
    &lt;entry /&gt;
&lt;/feed&gt;
</pre>
<p><code>doc.evaluate('//entry', doc, nsResolver, XPathResult.ANY_TYPE, null)</code> will return an empty set, where <code>nsResolver</code> is the resolver returned by <code>createNSResolver</code>.  Passing a <code>null</code> resolver doesn't work any better, either.
</p><p>One possible workaround is to create a custom resolver that returns the correct default namespace (the Atom namespace in this case).  E.g.:
</p>
<pre>function resolver() {
    return 'http://www.w3.org/2005/Atom';
}
doc.evaluate('//entry', doc, resolver, XPathResult.ANY_TYPE, null)
</pre>
<p>Note that a more complex resolver will be required if the document uses multiple namespaces.
</p>
<h4 name="XPathResult_Defined_Constants">XPathResult Defined Constants</h4>
<table class="standard-table">

<tbody><tr>
<td class="header">Result Type Defined Constant
</td><td class="header">Value
</td><td class="header">Description
</td></tr>

<tr>
<td>ANY_TYPE
</td><td>0
</td><td>A result set containing whatever type naturally results from evaluation of the expression. Note that if the result is a node-set then UNORDERED_NODE_ITERATOR_TYPE is always the resulting type.
</td></tr>

<tr>
<td>NUMBER_TYPE
</td><td>1
</td><td>A result containing a single number. This is useful for example, in an XPath expression using the <code>count()</code> function.
</td></tr>

<tr>
<td>STRING_TYPE
</td><td>2
</td><td>A result containing a single string.
</td></tr>

<tr>
<td>BOOLEAN_TYPE
</td><td>3
</td><td>A result containing a single boolean value. This is useful for example, in an XPath expression using the <code>not()</code> function.
</td></tr>

<tr>
<td>UNORDERED_NODE_ITERATOR_TYPE
</td><td>4
</td><td>A result node-set containing all the nodes matching the expression. The nodes may not necessarily be in the same order that they appear in the document.
</td></tr>

<tr>
<td>ORDERED_NODE_ITERATOR_TYPE
</td><td>5
</td><td>A result node-set containing all the nodes matching the expression. The nodes in the result set are in the same order that they appear in the document.
</td></tr>

<tr>
<td>UNORDERED_NODE_SNAPSHOT_TYPE
</td><td>6
</td><td>A result node-set containing snapshots of all the nodes matching the expression. The nodes may not necessarily be in the same order that they appear in the document.
</td></tr>

<tr>
<td>ORDERED_NODE_SNAPSHOT_TYPE
</td><td>7
</td><td>A result node-set containing snapshots of all the nodes matching the expression. The nodes in the result set are in the same order that they appear in the document.
</td></tr>

<tr>
<td>ANY_UNORDERED_NODE_TYPE
</td><td>8
</td><td>A result node-set containing any single node that matches the expression. The node is not necessarily the first node in the document that matches the expression.
</td></tr>

<tr>
<td>FIRST_ORDERED_NODE_TYPE
</td><td>9
</td><td>A result node-set containing the first node in the document that matches the expression.
</td></tr>
</tbody></table>
<div class="originaldocinfo">
<h2 name="Original_Document_Information"> Original Document Information </h2>
<ul><li> Based Upon Original Document <a class="external" href="http://www-xray.ast.cam.ac.uk/~jgraham/mozilla/xpath-tutorial.html">Mozilla XPath Tutorial</a>
</li><li> Original Source Author: James Graham.
</li><li> Other Contributors: James Thompson.
</li><li> Last Updated Date: 2006-3-25.
</li></ul>
</div>
{{ wiki.languages( { "ja": "ja/Introduction_to_using_XPath_in_JavaScript", "ko": "ko/Introduction_to_using_XPath_in_JavaScript" } ) }}
Revert to this revision