mozilla

Revision 275662 of Introduction à l'utilisation de XPath avec JavaScript

  • Raccourci de la révision : Introduction_à_l'utilisation_de_XPath_avec_JavaScript
  • Titre de la révision : Introduction à l'utilisation de XPath avec JavaScript
  • ID de la révision : 275662
  • Créé :
  • Créateur : Fredchat
  • Version actuelle ? Non
  • Commentaire /* Implementing a Default Namespace Resolver */

Contenu de la révision

{{template.Traduction_en_cours("Introduction to using XPath in JavaScript")}} Ce document décrit l'utilisation de l'interface d'utilisation de XPath dans JavaScript en interne, dans les extensions et depuis les sites Web. Mozilla implémente une partie importante de DOM 3 XPath (en). Cele signifie que les expressions XPath peuvent être utilisées sur des documents HTML et XML.

La principale interface pour l'utilisation de XPath est la fonction evaluate de l'objet document.

document.evaluate

Cette méthode évalue les expressions XPath dans un document XML (y compris les documents HTML), et retourne un objet XPathResult, que peut être un nœud unique ou un ensemble de nœud. La documentation existante sur cette méthode se trouve à la page DOM:document.evaluate mais elle est plutôt succincte comparé à nos besoins actuels, nous l'examinerons de façon plus complète dans la suite de ce document.

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

Paramètres

La fonction evaluate prend cinq arguments au total :

xpathExpression
Une chaîne contenant l'expression XPath à évaluer.
contextNode
Un nœud du document dans lequel xpathExpression doit être évaluée, incluant n'importe lequel de ses descendants. Le nœud document est le plus couramment utilisé.
namespaceResolver
Une fonction qui sera passée à n'importe quel préfixe d'espace de nommage contenu dans xpathExpression qui retourne une chaîne représentant l'URI de l'espace de nommage associé au préfixe. Cela permet la conversion entre le préfixe utilisé dans les expressions XPath et les différents préfixes éventuellement utilisés dans le document. Cette fonction peut être :
  • Créé à l'aide de la méthode createNSResolver d'un objet XPathEvaluator. Vous devriez utiliser cela virtuellement tout le temps.
  • null, qui peut être utilisé pour les documents HTML ou lorsqu'aucun préfixe n'est utilisé. Remarquez que si l'xpathExpression contient un préfixe d'espace de nommage cela entraînera une DOMException envoyée avec le code NAMESPACE_ERR.
  • Une fonction personnalisée par l'utilisateur. Voir la section Using a User Defined Namespace Resolver dans l'annexe pour plus de détails.
resultType
Une constante qui définit le type de résultat désiré à retourner comme résultat de l'évaluation. La constante la plus courante est XPathResult.ANY_TYPE qui retournera les résultats de l'expression XPath dans le type le plus naturel. Il y a une section de l'annexe qui contient une liste complète des constantes disponibles. Elles sont expliquées dans la section #Définition du type de retour ci-dessous.
  • result : Soit un objet XPathResult existant qui sera réutilisé pour retourner les résultats, soit null qui peut être utilisé pour créer un nouvel objet XPathResult.

Valeur retournée

Retourne xpathResult, qui est un objet XPathResult du type défini dans le paramètre resultType. L'interface XPathResult est définie dans ce document.

Implémentation d'un résolveur d'espaces de nommage par défaut

Nous créons en résolveur d'espace de nommage à l'aide de la méthode createNSResolver de l'objet document.

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

Ou alternativement en utilisant la méthode <code>createNSResolver</code> d'un objet <code>XPathEvaluator</code>. <pre> var xpEvaluator = new XPathEvaluator(); var nsResolver = xpEvaluator.createNSResolver( contextNode.ownerDocument == null ? contextNode.documentElement : contextNode.ownerDocument.documentElement ); </pre> Puis nous passons document.evaluate, la variable nsResolver comme paramètre namespaceResolver.

Notez que XPath définit les QNames sans les préfixes pour ne correspondre qu'aux éléments de l'espace de nommage null. Il n'existe aucun moyen dans XPath pour récupérer l'espace de nommage par défaut. Pour coupler des éléments ou des attributs dans un espace de nommage non nul, vous devez utiliser prefixed name tests, et créer un résolveur d'espace de nommage qui fera correspondre le préfix avec l'espace de nommage. Apprenez-en plus sur la façon de créer un résolveur d'espace de nommage personnalisé ci-dessous.

Définition du type de retour

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.

Constantes définies de XPathResult

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.

Informations sur le document original

  • Document original : Mozilla XPath Tutorial (en)
  • Auteur(s) : James Graham.
  • Autre(s) contributeur(s): James Thompson.
  • Dernière mise à jour : 25 mars 2006

Interwiki Languages Links

{{ wiki.languages( { "en": "en/Introduction_to_using_XPath_in_JavaScript", "ja": "ja/Introduction_to_using_XPath_in_JavaScript", "ko": "ko/Introduction_to_using_XPath_in_JavaScript" } ) }}

Source de la révision

<p>
{{template.Traduction_en_cours("Introduction to using XPath in JavaScript")}}
Ce document décrit l'utilisation de l'interface d'utilisation de <a href="fr/XPath">XPath</a> dans JavaScript en interne, dans les extensions et depuis les sites Web. Mozilla implémente une partie importante de <a class="external" href="http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html">DOM 3 XPath (en)</a>. Cele signifie que les expressions XPath peuvent être utilisées sur des documents HTML et XML.
</p><p>La principale interface pour l'utilisation de XPath est la fonction <a href="fr/DOM/document.evaluate">evaluate</a> de l'objet  <a href="fr/DOM/document">document</a>.
</p>
<h2 name="document.evaluate">document.evaluate</h2>
<p>Cette méthode évalue les expressions <a href="fr/XPath">XPath</a> dans un document <a href="fr/XML">XML</a> (y compris les documents HTML), et retourne un objet <code>XPathResult</code>, que peut être un nœud unique ou un ensemble de nœud. La documentation existante sur cette méthode se trouve à la page <a href="fr/DOM/document.evaluate">DOM:document.evaluate</a> mais elle est plutôt succincte comparé à nos besoins actuels, nous l'examinerons de façon plus complète dans la suite de ce document.
</p>
<pre class="eval">var xpathResult = document.evaluate( xpathExpression, contextNode, namespaceResolver, resultType, result );
</pre>
<h3 name="Param.C3.A8tres">Paramètres</h3>
<p>La fonction <a href="fr/DOM/document.evaluate">evaluate</a> prend cinq arguments au total :
</p>
<dl><dt> <code>xpathExpression</code>
</dt><dd> Une chaîne contenant l'expression XPath à évaluer.
</dd><dt> <code>contextNode</code>
</dt><dd> Un nœud du document dans lequel <code>xpathExpression</code> doit être évaluée, incluant n'importe lequel de ses descendants. Le nœud <a href="fr/DOM/document">document</a> est le plus couramment utilisé.
</dd><dt> <code>namespaceResolver</code>
</dt><dd> Une fonction qui sera passée à n'importe quel préfixe d'espace de nommage contenu dans <code>xpathExpression</code> qui retourne une chaîne représentant l'URI de l'espace de nommage associé au préfixe. Cela permet la conversion entre le préfixe utilisé dans les expressions XPath et les différents préfixes éventuellement utilisés dans le document. Cette fonction peut être :
</dd></dl>
<ul><li> <a href="#Implementing_a_Default_Namespace_Resolver">Créé</a> à l'aide de la méthode <code><a href="fr/DOM/document.createNSResolver">createNSResolver</a></code> d'un objet <code><a class="external" href="http://www.xulplanet.com/references/objref/XPathEvaluator.html">XPathEvaluator</a></code>. Vous devriez utiliser cela virtuellement tout le temps.
</li><li> <code>null</code>, qui peut être utilisé pour les documents HTML ou lorsqu'aucun préfixe n'est utilisé. Remarquez que si l'<code>xpathExpression</code> contient un préfixe d'espace de nommage cela entraînera une  <code>DOMException</code> envoyée avec le code <code>NAMESPACE_ERR</code>.
</li><li> Une fonction personnalisée par l'utilisateur. Voir la section <a href="#Implementing_a_User_Defined_Namespace_Resolver">Using a User Defined Namespace Resolver</a> dans l'annexe pour plus de détails.
</li></ul>
<dl><dt> <code>resultType</code>
</dt><dd> Une <a href="#Constantes_d.C3.A9finies_de_XPathResult">constante</a> qui définit le type de résultat désiré à retourner comme résultat de l'évaluation. La constante la plus courante est <code>XPathResult.ANY_TYPE</code> qui retournera les résultats de l'expression XPath dans le type le plus naturel. Il y a une section de l'annexe qui contient une liste complète des <a href="#Constantes_d.C3.A9finies_de_XPathResult">constantes disponibles</a>. Elles sont expliquées dans la section <a href="#D.C3.A9finition_du_type_de_retour">#Définition du type de retour</a> ci-dessous.
</dd></dl>
<ul><li> <code>result</code> : Soit un objet <code>XPathResult</code> existant qui sera réutilisé pour retourner les résultats, soit <code>null</code> qui peut être utilisé pour créer un nouvel objet <code>XPathResult</code>.
</li></ul>
<h3 name="Valeur_retourn.C3.A9e">Valeur retournée</h3>
<p>Retourne <code>xpathResult</code>, qui est un objet <code>XPathResult</code> du type <a href="#D.C3.A9finition_du_type_de_retour">défini</a> dans le paramètre <code>resultType</code>. L'interface <code>XPathResult</code> est définie dans ce <a class="external" href="http://lxr.mozilla.org/seamonkey/source/dom/public/idl/xpath/nsIDOMXPathResult.idl">document</a>.
</p>
<h3 name="Impl.C3.A9mentation_d.27un_r.C3.A9solveur_d.27espaces_de_nommage_par_d.C3.A9faut">Implémentation d'un résolveur d'espaces de nommage par défaut</h3>
<p>Nous créons en résolveur d'espace de nommage à l'aide de la méthode <code>createNSResolver</code> de l'objet <a href="fr/DOM/document">document</a>.
</p>
<pre class="eval">var nsResolver = document.createNSResolver( contextNode.ownerDocument == null ? contextNode.documentElement : contextNode.ownerDocument.documentElement );
</pre>
<p><span class="comment">Ou alternativement en utilisant la méthode &lt;code&gt;createNSResolver&lt;/code&gt; d'un objet &lt;code&gt;XPathEvaluator&lt;/code&gt;.  &lt;pre&gt; var xpEvaluator = new XPathEvaluator();  var nsResolver = xpEvaluator.createNSResolver( contextNode.ownerDocument == null ? contextNode.documentElement : contextNode.ownerDocument.documentElement ); &lt;/pre&gt;</span>
Puis nous passons <code>document.evaluate</code>, la variable <code>nsResolver</code> comme paramètre <code>namespaceResolver</code>.
</p><p>Notez que XPath définit les <code>QNames</code> sans les préfixes pour ne correspondre qu'aux éléments de l'espace de nommage <code>null</code>. Il n'existe aucun moyen dans XPath pour récupérer l'espace de nommage par défaut. Pour coupler des éléments ou des attributs dans un espace de nommage non nul, vous devez utiliser <b>prefixed name tests</b>, et créer un résolveur d'espace de nommage qui fera correspondre le préfix avec l'espace de nommage. Apprenez-en plus sur la façon de <a href="#Impl.C3.A9mentation_d.27un_r.C3.A9solveur_d.27espace_de_nommage_personnalis.C3.A9">créer un résolveur d'espace de nommage personnalisé</a> ci-dessous.
</p>
<h3 name="D.C3.A9finition_du_type_de_retour">Définition du type de retour</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="fr/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_Nodes">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="fr/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="fr/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="fr/XMLHttpRequest">XMLHttpRequest</a></code> object to load the document synchronously, the variable <code>xmlDoc</code> will contain the document as an <code><a href="fr/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="fr/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="Constantes_d.C3.A9finies_de_XPathResult">Constantes définies de XPathResult</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="Informations_sur_le_document_original"> Informations sur le document original </h2>
<ul><li> Document original : <a class="external" href="http://www-xray.ast.cam.ac.uk/~jgraham/mozilla/xpath-tutorial.html">Mozilla XPath Tutorial (en)</a>
</li><li> Auteur(s) : James Graham.
</li><li> Autre(s) contributeur(s): James Thompson.
</li><li> Dernière mise à jour : 25 mars 2006
</li></ul>
</div>
<p><span class="comment">Interwiki Languages Links</span>
</p>{{ wiki.languages( { "en": "en/Introduction_to_using_XPath_in_JavaScript", "ja": "ja/Introduction_to_using_XPath_in_JavaScript", "ko": "ko/Introduction_to_using_XPath_in_JavaScript" } ) }}
Revenir à cette révision