Introduction à l/g'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 : 275675
  • Créé :
  • Créateur : BenoitL
  • Version actuelle ? Non
  • Commentaire /* Annexe */ relecture

Contenu de la révision

{{wiki.template('Traduction_à_relire')}} Ce document décrit l'interface pour utiliser XPath dans JavaScript, que ce soit en interne, dans les extensions et depuis les sites Web. Mozilla implémente une partie importante de DOM 3 XPath (en). Cela 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, qui peut être un nœud unique ou un ensemble de nœuds. La documentation existante sur cette méthode se trouve à la page DOM:document.evaluate mais elle est plutôt succincte comparée à 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 pour lequel l'expression xpathExpression doit être évaluée, ainsi que l'ensemble de ses descendants. Le nœud document est le plus couramment utilisé.
namespaceResolver
Une fonction à laquelle sera passé tout préfixe d'espace de nommage contenu dans l'expression xpathExpression et qui renvoie une chaîne représentant l'URI de l'espace de nommage associé à ce 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éée à l'aide de la méthode createNSResolver d'un objet XPathEvaluator. C'est la solution à utiliser à peu près tout le temps.
  • Une valeur null, qui peut être utilisé pour les documents HTML ou lorsqu'aucun préfixe n'est utilisé. Remarquez que si l'expression xpathExpression contient un préfixe d'espace de nommage cela déclenchera une exception DOMException portant le code NAMESPACE_ERR.
  • Une fonction personnalisée définie par l'utilisateur. Voir la section Implémentation d'un résolveur d'espace de nommage personnalisé dans l'annexe pour plus de détails.
resultType
Une constante qui définit le type de résultat à renvoyer comme résultat de l'évaluation. La constante la plus courante est XPathResult.ANY_TYPE qui renverra un résultat du type le plus naturel par rapport à l'expression XPath. Une section de l'annexe 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 contenir les résultats, soit la valeur null qui peut être utilisée pour créer un nouvel objet XPathResult.

Valeur de retour

Renvoie 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

On crée un 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> On lui passe ensuite document.evaluate, la variable nsResolver comme paramètre namespaceResolver.

véracité du paragraphe suivant à vérifier avec la doc du w3c Notez que XPath définit que les QNames sans préfixe ne peuvent 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

La variable xpathResult renvoyée par document.evaluate peut être composée de nœuds individuels (types simples), ou un groupe de nœuds (types d'ensembles de nœuds).

Types simples

Lorsque le type de résultat spécifié dans resultType est soit :

  • NUMBER_TYPE — un nombre
  • STRING_TYPE — une chaîne
  • BOOLEAN_TYPE — une valeur booléenne

On obtiendra la valeur de retour de l'expression en accédant respectivement aux propriétés suivantes de l'objet XPathResult :

  • numberValue
  • stringValue
  • booleanValue
Exemple

Cet exemple utilise l'expression XPath count(//p) pour obtenir le nombre d'éléments <p> présents dans le document HTML :

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

alert( 'Ce document contient ' + paragraphCount.numberValue + ' éléments de paragraphe' );

Même si JavaScript convertira un nombre en chaîne pour l'affichage, l'interface XPath ne fera pas automatiquement la conversion du résultat numérique si la propriété stringValue est demandée. Ainsi, le code suivant ne fonctionnera pas :

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

alert( 'Ce document contient ' + paragraphCount.stringValue + ' éléments de paragraphe' );

Au lieu de cela, il déclenchera une exception pourtant le code NS_DOM_TYPE_ERROR.

Types d'ensembles de nœuds

L'objet XPathResult permet de renvoyer les ensembles de nœuds sous la forme de trois types principaux :

Itérateurs

Lorsque le type de résultat spécifié dans le paramètre resultType est soit :

  • UNORDERED_NODE_ITERATOR_TYPE
  • ORDERED_NODE_ITERATOR_TYPE

L'objet XPathResult renvoyé sera un ensemble de nœuds correspondant à l'expression se comportant comme un itérateur. On pourra accéder individuellement aux nœuds qu'il contient en utilisant la méthode iterateNext() de l'objet XPathResult.

Lorsque tous les nœuds ont été parcourus, iterateNext() renverra null.

Notez cependant que si le document le document est modifié (l'arbre du document est modifié) entre les itérations, l'itérateur sera invalidé et la propriété invalidIteratorState de XPathResult deviendra true. Une exception NS_ERROR_DOM_INVALID_STATE_ERR sera également déclenchée.

Exemple d'itérateur
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( 'Erreur : L'arbre du document a été modifié pendant l'itération ' + e );
}
Snapshots

Lorsque le type de résultat spécifié dans le paramètre resultType est l'une des valeurs suivantes :

  • UNORDERED_NODE_SNAPSHOT_TYPE
  • ORDERED_NODE_SNAPSHOT_TYPE

L'objet XPathResult renvoyé sera un ensemble statique de nœuds correspondant à l'expression. L'accès à chaque nœud se fera au travers de la méthode snapshotItem(itemNumber) de l'objet XPathResult, où itemNumber est l'indice du nœud à récupérer. On peut accéder au nombre total de nœuds contenus dans l'ensemble par la propriété snapshotLength.

Les snapshots ne changent pas avec les mutations du document. Aussi, contrairement aux itérateurs, le snapshot ne deviendra pas invalide mais peut ne plus correspondre au document actuel. Par exemple, des nœuds peuvent avoir été déplacés, il peut contenir des nœuds qui n'existent plus ou de nouveaux nœuds peuvent avoir été ajoutés.

Exemple de snapshot
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 );
}
Premier nœud

Lorsque le type de résultat spécifié dans le paramètre resultType est l'une des valeurs suivantes :

  • ANY_UNORDERED_NODE_TYPE
  • FIRST_ORDERED_NODE_TYPE

L'objet XPathResult renvoyé n'est que le premier nœud trouvé correspondant à l'expression XPath. On peut y accéder à l'aide de la propriété singleNodeValue de l'objet XPathResult. Celle-ci vaudra null si l'ensemble de nœuds est vide.

Notez que pour le sous-type non ordonné (le premier), le nœud unique renvoyé ne sera peut-être pas le premier nœud dans l'ordre du document. Dans le cas du sous-type ordonné (le second), vous pouvez être sûr d'obtenir le premier nœud correspond dans l'ordre du document.

Exemple de premier nœud
var firstPhoneNumber = document.evaluate('//phoneNumber', documentNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null );

dump( 'Le premier numéro de téléphone trouvé est ' + firstPhoneNumber.singleNodeValue.textContent );

La constante ANY_TYPE

Lorsque le type de résultat spécifié dans le paramètre resultType est la valeur ANY_TYPE, l'objet XPathResult renvoyé pourra être de n'importe quel type, c'est-à-dire du type résultant le plus naturellement de l'évaluation de l'expression.

Il peut s'agir de n'importe lequel des types simples (NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE), mais si le type du résultat retourné est un ensemble de nœuds alors il ne pourra être que du type UNORDERED_NODE_ITERATOR_TYPE.

Pour déterminer le type utilisé après l'évaluation, on utilisera la propriété resultType de l'objet XPathResult. Les valeurs constantes de cette propriété sont définies dans l'annexe.

None Yet =====Exemple Any_Type===== <pre> </pre>

Exemples

Dans un document HTML

Le code suivant est destiné à être inséré dans un fragment JavaScript intégré ou lié au document HTML qui devra être évalué par l'expression XPath.

Pour extraire tous les éléments d'en-tête <h2> d'un document HTML à l'aide de XPath, l'expression xpathExpression est simplement '//h2', où // est l'opérateur descendant récursif (ou RDO) qui correspond aux éléments dont la propriété nodeName est h2 n'importe où dans l'arbre du document. Le code complet pour cela est : link to introductory xpath doc

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

Notez que, comme HTML ne possède pas d'espace de nommage, null a été passé comme paramètre namespaceResolver.

Comme le but est de chercher les en-têtes dans l'intégralité du document, on utilise l'objet document lui-même comme paramètre contextNode.

Le résultat de cette expression est un objet XPathResult. Pour connaître le type de résultat renvoyé, il convient d'évaluer la propriété resultType de l'objet renvoyé. Dans notre cas, il sera évalué à 4, c'est donc un UNORDERED_NODE_ITERATOR_TYPE. Il s'agit du type de retour par défaut lorsque le résultat de l'expression XPath est un ensemble de nœuds. Il permet d'accéder à un seul nœud à la fois et ne renvoie pas les nœuds dans un ordre particulier. Pour accéder à ceux-ci, on utilise la méthode iterateNext() de l'objet renvoyé :

var thisHeading = headings.iterateNext();

var alertText = 'Les en-têtes de niveau 2 présents dans ce document sont :\n'

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

Une fois l'itération effectuée sur un nœud, nous avons accès à toutes les Interfaces DOM standards de ce nœud. Après avoir parcouru tous les éléments h2 renvoyés à partir de notre expression, chaque nouvel appel à iterateNext() donnera null.

Évaluation d'un document XML appartenant à une extension

L'exemple suivant utilise un document XML situé à l'adresse <tt>chrome://yourextension/content/peopleDB.xml</tt>.

<?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>

Pour rendre les contenus du document XML accessibles depuis l'extension, on crée un objet XMLHttpRequest pour charger le document de façon synchrone. La variable xmlDoc contiendra le document comme un objet XMLDocument sur lequel on pourra utiliser la méthode evaluate.

JavaScript utilisé dans les documents XUL/js des extensions.

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 );

Annexes

Implémentation d'un résolveur d'espace de nommage personnalisé

Cet exemple ne sert que d'illustration. Cette fonction devra déterminer les préfixes d'espaces de nommage depuis l'expression xpathExpression et renvoyer l'URI correspondant au préfixe trouvé. Par exemple, l'expression :

'//xhtml:td/mathml:math'

sélectionnera toutes les expressions MathML qui sont les descendantes des éléments de cellules de tableau (X)HTML.

Afin d'associer le préfixe mathml: avec l'URI d'espace de nommage 'http://www.w3.org/1998/Math/MathML' et xhtml: avec l'URI http://www.w3.org/1999/xhtml, on fournit une fonction :

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

L'appel à document.evaluate ressemblera alors à :

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

Implémentation d'un espace de nommage par défaut pour les documents XML

Comme indiqué précédemment dans le section #Implémentation d'un résolveur d'espaces de nommage par défaut, le résolveur par défaut ne gère pas l'espace de nommage par défaut pour les documents XML. Par exemple, avec ce 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) renverra un ensemble vide, où nsResolver est le résolveur renvoyé par createNSResolver. Passer un résolveur null ne fonctionnera pas mieux.

Une alternative possible est de créer un résolveur personnalisé qui renverra le bon espace de nommage (l'espace de nommage Atom dans ce cas). Par exemple :

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

Un résolveur plus complexe sera nécessaire si le document utilise plusieurs espaces de nommage.

Constantes définies de XPathResult

Constante de type de résultat Valeur Description
ANY_TYPE 0 Un ensemble contenant n'importe quel type qui résulte naturellement de l'évaluation de l'expression. Notez que s'il s'agit d'un ensemble de nœuds, le type résultant sera toujours UNORDERED_NODE_ITERATOR_TYPE.
NUMBER_TYPE 1 Un résultat contenant un seul nombre. C'est utile, par exemple, dans une expression XPath utilisant la fonction count().
STRING_TYPE 2 Un résultat contenant une seule chaîne de caractères.
BOOLEAN_TYPE 3 Un résultat contenant une seule valeur booléenne. C'est utile, par exemple, dans une expression XPath utilisant la fonction not().
UNORDERED_NODE_ITERATOR_TYPE 4 Un ensemble de nœuds contenant tous les nœuds vérifiant l'expression. Les nœuds ne sont pas nécessairement dans le même ordre que celui dans lequel ils apparaissent dans le document.
ORDERED_NODE_ITERATOR_TYPE 5 Un ensemble de nœuds contenant tous les nœuds vérifiant l'expression. Les nœuds du résultat sont dans le même ordre que celui dans lequel ils apparaissent dans le document.
UNORDERED_NODE_SNAPSHOT_TYPE 6 Un ensemble de nœuds contenant une capture instantanée (snapshot) de tous les nœuds vérifiant l'expression. Les nœuds ne sont pas nécessairement dans le même ordre que celui dans lequel ils apparaissent dans le document.
ORDERED_NODE_SNAPSHOT_TYPE 7 Un ensemble de nœuds contenant une capture instantanée (snapshot) de tous les nœuds vérifiant l'expression. Les nœuds du résultat sont dans le même ordre que celui dans lequel ils apparaissent dans le document.
ANY_UNORDERED_NODE_TYPE 8 Un ensemble de nœuds contenant un nœud quelconque vérifiant l'expression. Le nœud n'est pas nécessairement le premier dans l'ordre du document qui correspond à l'expression.
FIRST_ORDERED_NODE_TYPE 9 Un ensemble de nœuds contenant le premier nœud du document vérifiant l'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>
{{wiki.template('Traduction_à_relire')}}
Ce document décrit l'interface pour utiliser <a href="fr/XPath">XPath</a> dans JavaScript, que ce soit 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>. Cela 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>, qui peut être un nœud unique ou un ensemble de nœuds. 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ée à 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 pour lequel l'expression <code>xpathExpression</code> doit être évaluée, ainsi que l'ensemble 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 à laquelle sera passé tout préfixe d'espace de nommage contenu dans l'expression <code>xpathExpression</code> et qui renvoie une chaîne représentant l'URI de l'espace de nommage associé à ce 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="#Impl.C3.A9mentation_d.27un_r.C3.A9solveur_d.27espaces_de_nommage_par_d.C3.A9faut">Créée</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>. C'est la solution à utiliser à peu près tout le temps.
</li><li> Une valeur <code>null</code>, qui peut être utilisé pour les documents HTML ou lorsqu'aucun préfixe n'est utilisé. Remarquez que si l'expression <code>xpathExpression</code> contient un préfixe d'espace de nommage cela déclenchera une exception <code>DOMException</code> portant le code <code>NAMESPACE_ERR</code>.
</li><li> Une fonction personnalisée définie par l'utilisateur. Voir la section <a href="#Impl.C3.A9mentation_d.27un_r.C3.A9solveur_d.27espace_de_nommage_personnalis.C3.A9">Implémentation d'un résolveur d'espace de nommage personnalisé</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 à renvoyer comme résultat de l'évaluation. La constante la plus courante est <code>XPathResult.ANY_TYPE</code> qui renverra un résultat du type le plus naturel par rapport à l'expression XPath. Une section de l'annexe 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><dt> <code>result</code> </dt><dd> Soit un objet <code>XPathResult</code> existant qui sera réutilisé pour contenir les résultats, soit la valeur <code>null</code> qui peut être utilisée pour créer un nouvel objet <code>XPathResult</code>.
</dd></dl>
<h3 name="Valeur_de_retour">Valeur de retour</h3>
<p>Renvoie <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>On crée un 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>
On lui passe ensuite <code>document.evaluate</code>, la variable <code>nsResolver</code> comme paramètre <code>namespaceResolver</code>.
</p><p><span class="comment">véracité du paragraphe suivant à vérifier avec la doc du w3c</span>
Notez que XPath définit que les <code>QNames</code> sans préfixe ne peuvent 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>La variable <code>xpathResult</code> renvoyée par <code>document.evaluate</code> peut être composée de nœuds individuels (<a href="#Types_simples">types simples</a>), ou un groupe de nœuds (<a href="#Types_d.27ensembles_de_n.C5.93uds">types d'ensembles de nœuds</a>).
</p>
<h4 name="Types_simples"> Types simples </h4>
<p>Lorsque le type de résultat spécifié dans <code>resultType</code> est soit :
</p>
<ul><li> <code>NUMBER_TYPE</code> — un nombre
</li><li> <code>STRING_TYPE</code> — une chaîne
</li><li> <code>BOOLEAN_TYPE</code> — une valeur booléenne
</li></ul>
<p>On obtiendra la valeur de retour de l'expression en accédant respectivement aux propriétés suivantes de l'objet <code>XPathResult</code> :
</p>
<ul><li> <code>numberValue</code>
</li><li> <code>stringValue</code>
</li><li> <code>booleanValue</code>
</li></ul>
<h5 name="Exemple"> Exemple </h5>
<p>Cet exemple utilise l'expression XPath <code><a href="fr/XPath/Fonctions/count">count(//p)</a></code> pour obtenir le nombre d'éléments <code>&lt;p&gt;</code> présents dans le document HTML :
</p>
<pre>var paragraphCount = document.evaluate( 'count(//p)', document, null, XPathResult.ANY_TYPE, null );

alert( 'Ce document contient ' + paragraphCount.numberValue + ' éléments de paragraphe' );
</pre>
<p>Même si JavaScript convertira un nombre en chaîne pour l'affichage, l'interface XPath ne fera pas automatiquement la conversion du résultat numérique si la propriété <code>stringValue</code> est demandée. Ainsi, le code suivant ne fonctionnera <b>pas</b> :
</p>
<pre>var paragraphCount = document.evaluate('count(//p)', document, null, XPathResult.ANY_TYPE, null );

alert( 'Ce document contient ' + paragraphCount.stringValue + ' éléments de paragraphe' );
</pre>
<p>Au lieu de cela, il déclenchera une exception pourtant le code <code>NS_DOM_TYPE_ERROR</code>.
</p>
<h4 name="Types_d.27ensembles_de_n.C5.93uds"> Types d'ensembles de nœuds </h4>
<p>L'objet <code>XPathResult</code> permet de renvoyer les ensembles de nœuds sous la forme de trois types principaux :
</p>
<ul><li> <a href="#It.C3.A9rateurs">Itérateurs</a>
</li><li> <a href="#Snapshots">Snapshots</a>
</li><li> <a href="#Premiers_n.C5.93uds">Premiers nœuds</a>
</li></ul>
<h5 name="It.C3.A9rateurs"> Itérateurs </h5>
<p>Lorsque le type de résultat spécifié dans le paramètre <code>resultType</code> est soit :
</p>
<ul><li> <code>UNORDERED_NODE_ITERATOR_TYPE</code>
</li><li> <code>ORDERED_NODE_ITERATOR_TYPE</code>
</li></ul>
<p>L'objet <code>XPathResult</code> renvoyé sera un ensemble de nœuds correspondant à l'expression se comportant comme un itérateur. On pourra accéder individuellement aux nœuds qu'il contient en utilisant la méthode <code>iterateNext()</code> de l'objet <code>XPathResult</code>. 
</p><p>Lorsque tous les nœuds ont été parcourus, <code>iterateNext()</code> renverra <code>null</code>.
</p><p>Notez cependant que si le document le document est modifié (l'arbre du document est modifié) entre les itérations, l'itérateur  sera invalidé et la propriété <code>invalidIteratorState</code> de <code>XPathResult</code> deviendra  <code>true</code>. Une exception <code>NS_ERROR_DOM_INVALID_STATE_ERR</code> sera également déclenchée.
</p>
<h6 name="Exemple_d.27it.C3.A9rateur"> Exemple d'itérateur </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( 'Erreur : L'arbre du document a été modifié pendant l'itération ' + e );
}
</pre>
<h5 name="Snapshots"> Snapshots </h5>
<p>Lorsque le type de résultat spécifié dans le paramètre <code>resultType</code> est l'une des valeurs suivantes :
</p>
<ul><li> <code>UNORDERED_NODE_SNAPSHOT_TYPE</code>
</li><li> <code>ORDERED_NODE_SNAPSHOT_TYPE</code>
</li></ul>
<p>L'objet <code>XPathResult</code> renvoyé sera un ensemble statique de nœuds correspondant à l'expression. L'accès à chaque nœud se fera au travers de la méthode <code>snapshotItem(itemNumber)</code> de l'objet <code>XPathResult</code>, où <code>itemNumber</code> est l'indice du nœud à récupérer. On peut accéder au nombre total de nœuds contenus dans l'ensemble par la propriété <code>snapshotLength</code>.
</p><p>Les snapshots ne changent pas avec les mutations du document. Aussi, contrairement aux itérateurs, le snapshot ne deviendra pas invalide mais peut ne plus correspondre au document actuel. Par exemple, des nœuds peuvent avoir été déplacés, il peut contenir des nœuds qui n'existent plus ou de nouveaux nœuds peuvent avoir été ajoutés.
</p>
<h6 name="Exemple_de_snapshot"> Exemple de snapshot </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="Premier_n.C5.93ud"> Premier nœud </h5>
<p>Lorsque le type de résultat spécifié dans le paramètre <code>resultType</code> est l'une des valeurs suivantes :
</p>
<ul><li> <code>ANY_UNORDERED_NODE_TYPE</code>
</li><li> <code>FIRST_ORDERED_NODE_TYPE</code>
</li></ul>
<p>L'objet <code>XPathResult</code> renvoyé n'est que le premier nœud trouvé correspondant à l'expression XPath. On peut y accéder à l'aide de la propriété <code>singleNodeValue</code> de l'objet <code>XPathResult</code>. Celle-ci vaudra <code>null</code> si l'ensemble de nœuds est vide.
</p><p>Notez que pour le sous-type non ordonné (le premier), le nœud unique renvoyé ne sera peut-être pas le premier nœud dans l'ordre du document. Dans le cas du sous-type ordonné (le second), vous pouvez être sûr d'obtenir le premier nœud correspond dans l'ordre du document.
</p>
<h6 name="Exemple_de_premier_n.C5.93ud"> Exemple de premier nœud </h6>
<pre>var firstPhoneNumber = document.evaluate('//phoneNumber', documentNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null );

dump( 'Le premier numéro de téléphone trouvé est ' + firstPhoneNumber.singleNodeValue.textContent );
</pre>
<h4 name="La_constante_ANY_TYPE"> La constante ANY_TYPE </h4>
<p>Lorsque le type de résultat spécifié dans le paramètre <code>resultType</code> est la valeur <code>ANY_TYPE</code>, l'objet <code>XPathResult</code> renvoyé pourra être de n'importe quel type, c'est-à-dire du type résultant le plus naturellement de l'évaluation de l'expression.
</p><p>Il peut s'agir de n'importe lequel des types simples (<code>NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE</code>), <b>mais</b> si le type du résultat retourné est un ensemble de nœuds alors il ne pourra être <b>que</b> du type <code>UNORDERED_NODE_ITERATOR_TYPE</code>.
</p><p>Pour déterminer le type utilisé après l'évaluation, on utilisera la propriété <code>resultType</code> de l'objet <code>XPathResult</code>. Les valeurs <a href="#Constantes_d.C3.A9finies_de_XPathResult">constantes</a> de cette propriété sont définies dans l'annexe.
</p><p><span class="comment">None Yet =====Exemple Any_Type===== &lt;pre&gt;  &lt;/pre&gt;</span>
</p>
<h2 name="Exemples"> Exemples </h2>
<h3 name="Dans_un_document_HTML"> Dans un document HTML </h3>
<p>Le code suivant est destiné à être inséré dans un fragment JavaScript intégré ou lié au document HTML qui devra être évalué par l'expression XPath.
</p><p>Pour extraire tous les éléments d'en-tête <code>&lt;h2&gt;</code> d'un document HTML à l'aide de XPath, l'expression <code>xpathExpression</code> est simplement '<code>//h2</code>', où <code>//</code> est l'opérateur descendant récursif (ou RDO) qui correspond aux éléments dont la propriété <code>nodeName</code> est <code>h2</code> n'importe où dans l'arbre du document. Le code complet pour cela est :
<span class="comment">link to introductory xpath doc</span>
</p>
<pre class="eval">var headings = document.evaluate('//h2', document, null, XPathResult.ANY_TYPE, null );
</pre>
<p>Notez que, comme HTML ne possède pas d'espace de nommage, <code>null</code> a été passé comme paramètre <code>namespaceResolver</code>.
</p><p>Comme le but est de chercher les en-têtes dans l'intégralité du document, on utilise l'objet <a href="fr/DOM/document">document</a> lui-même comme paramètre <code>contextNode</code>.
</p><p>Le résultat de cette expression est un objet <code>XPathResult</code>. Pour connaître le type de résultat renvoyé, il convient d'évaluer la propriété <code>resultType</code> de l'objet renvoyé. Dans notre cas, il sera évalué à <code>4</code>, c'est donc un <code>UNORDERED_NODE_ITERATOR_TYPE</code>. Il s'agit du type de retour par défaut lorsque le résultat de l'expression XPath est un ensemble de nœuds. Il permet d'accéder à un seul nœud à la fois et ne renvoie pas les nœuds dans un ordre particulier. Pour accéder à ceux-ci, on utilise la méthode <code>iterateNext()</code> de l'objet renvoyé :
</p>
<pre>var thisHeading = headings.iterateNext();

var alertText = 'Les en-têtes de niveau 2 présents dans ce document sont :\n'

while (thisHeading) {
  alertText += thisHeading.textContent + '\n';
  thisHeading = headings.iterateNext();
}
</pre>
<p>Une fois l'itération effectuée sur un nœud, nous avons accès à toutes les <a href="fr/Interfaces_DOM">Interfaces DOM</a> standards de ce nœud. Après avoir parcouru tous les éléments <code>h2</code> renvoyés à partir de notre expression, chaque nouvel appel à <code>iterateNext()</code> donnera <code>null</code>.
</p>
<h3 name=".C3.89valuation_d.27un_document_XML_appartenant_.C3.A0_une_extension"> Évaluation d'un document XML appartenant à une extension </h3>
<p>L'exemple suivant utilise un document XML situé à l'adresse <tt>chrome://yourextension/content/peopleDB.xml</tt>.
</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>Pour rendre les contenus du document XML accessibles depuis l'extension, on crée un objet <code><a href="fr/XMLHttpRequest">XMLHttpRequest</a></code> pour charger le document de façon synchrone. La variable <code>xmlDoc</code> contiendra le document comme un objet <code><a href="fr/XMLDocument">XMLDocument</a></code> sur lequel on pourra utiliser la méthode <code>evaluate</code>.
</p><p><i>JavaScript utilisé dans les documents XUL/js des extensions.</i>
</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="Annexes"> Annexes </h2>
<h4 name="Impl.C3.A9mentation_d.27un_r.C3.A9solveur_d.27espace_de_nommage_personnalis.C3.A9"> Implémentation d'un résolveur d'espace de nommage personnalisé </h4>
<p>Cet exemple ne sert que d'illustration. Cette fonction devra déterminer les préfixes d'espaces de nommage depuis l'expression <code>xpathExpression</code> et renvoyer l'URI correspondant au préfixe trouvé. Par exemple, l'expression :
</p>
<pre>'//xhtml:td/mathml:math'
</pre>
<p>sélectionnera toutes les expressions <a href="fr/MathML">MathML</a> qui sont les descendantes des éléments  de cellules de tableau (X)HTML.
</p><p>Afin d'associer le préfixe <code>mathml:</code> avec l'URI d'espace de nommage '<code>http://www.w3.org/1998/Math/MathML</code>' et <code>xhtml:</code> avec l'URI <code>http://www.w3.org/1999/xhtml</code>, on fournit une fonction :
</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>L'appel à <code>document.evaluate</code> ressemblera alors à :
</p>
<pre class="eval">document.evaluate( '//xhtml:td/mathml:math', document, nsResolver, XPathResult.ANY_TYPE, null );
</pre>
<h4 name="Impl.C3.A9mentation_d.27un_espace_de_nommage_par_d.C3.A9faut_pour_les_documents_XML"> Implémentation d'un espace de nommage par défaut pour les documents XML </h4>
<p>Comme indiqué précédemment dans le section <a href="#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</a>, le résolveur par défaut ne gère pas l'espace de nommage par défaut pour les documents XML. Par exemple, avec ce 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> renverra un ensemble vide, où <code>nsResolver</code> est le résolveur renvoyé par <code>createNSResolver</code>. Passer un résolveur <code>null</code> ne fonctionnera pas mieux.
</p><p>Une alternative possible est de créer un résolveur personnalisé qui renverra le bon espace de nommage (l'espace de nommage <i>Atom</i> dans ce cas). Par exemple :
</p>
<pre> function resolver() {
     return 'http://www.w3.org/2005/Atom';
 }
 doc.evaluate('//entry', doc, resolver, XPathResult.ANY_TYPE, null)
</pre>
<p>Un résolveur plus complexe sera nécessaire si le document utilise plusieurs espaces de nommage.
</p>
<h4 name="Constantes_d.C3.A9finies_de_XPathResult"> Constantes définies de XPathResult </h4>
<table class="standard-table">

<tbody><tr>
<td class="header">Constante de type de résultat
</td><td class="header">Valeur
</td><td class="header">Description
</td></tr>

<tr>
<td><code>ANY_TYPE</code>
</td><td>0
</td><td>Un ensemble contenant n'importe quel type qui résulte naturellement de l'évaluation de l'expression. Notez que s'il s'agit d'un ensemble de nœuds, le type résultant sera toujours <code>UNORDERED_NODE_ITERATOR_TYPE</code>.
</td></tr>

<tr>
<td><code>NUMBER_TYPE</code>
</td><td>1
</td><td>Un résultat contenant un seul nombre. C'est utile, par exemple, dans une expression XPath utilisant la fonction <code>count()</code>.
</td></tr>

<tr>
<td><code>STRING_TYPE</code>
</td><td>2
</td><td>Un résultat contenant une seule chaîne de caractères.
</td></tr>

<tr>
<td><code>BOOLEAN_TYPE</code>
</td><td>3
</td><td>Un résultat contenant une seule valeur booléenne. C'est utile, par exemple, dans une expression XPath utilisant la fonction <code>not()</code>.
</td></tr>

<tr>
<td><code>UNORDERED_NODE_ITERATOR_TYPE</code>
</td><td>4
</td><td>Un ensemble de nœuds contenant tous les nœuds vérifiant l'expression. Les nœuds ne sont pas nécessairement dans le même ordre que celui dans lequel ils apparaissent dans le document.
</td></tr>

<tr>
<td><code>ORDERED_NODE_ITERATOR_TYPE</code>
</td><td>5
</td><td>Un ensemble de nœuds contenant tous les nœuds vérifiant l'expression. Les nœuds du résultat sont dans le même ordre que celui dans lequel ils apparaissent dans le document.
</td></tr>

<tr>
<td><code>UNORDERED_NODE_SNAPSHOT_TYPE</code>
</td><td>6
</td><td>Un ensemble de nœuds contenant une capture instantanée (snapshot) de tous les nœuds vérifiant l'expression. Les nœuds ne sont pas nécessairement dans le même ordre que celui dans lequel ils apparaissent dans le document.
</td></tr>

<tr>
<td><code>ORDERED_NODE_SNAPSHOT_TYPE</code>
</td><td>7
</td><td>Un ensemble de nœuds contenant une capture instantanée (snapshot) de tous les nœuds vérifiant l'expression. Les nœuds du résultat sont dans le même ordre que celui dans lequel ils apparaissent dans le document.
</td></tr>

<tr>
<td><code>ANY_UNORDERED_NODE_TYPE</code>
</td><td>8
</td><td>Un ensemble de nœuds contenant un nœud quelconque vérifiant l'expression. Le nœud n'est pas nécessairement le premier dans l'ordre du document qui correspond à l'expression.
</td></tr>

<tr>
<td><code>FIRST_ORDERED_NODE_TYPE</code>
</td><td>9
</td><td>Un ensemble de nœuds contenant le premier nœud du document vérifiant l'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