Parcourir un arbe XML - Cours Javascript

Introduction

Les bases pour parcourir un xml

Ce cours javascript va vous aider à parcourir le document xml récupéré dans le httpRequest.responseXML

Vous trouverez des compléments d'informations dans le chapitre JAVASCRIPT DOM CORE

Récupérer le xml

Récupérer le xml

Lorsque vous récupérer la valeur du httpRequest.responseXML
cette dernière est de type document
Exemple :
Exemple de code :
httpRequest.onreadystatechange = function(){
  httpRequest.readyState == 0) {
    if (httpRequest.status == 200) {
      alert(httpRequest.responseXML);
    } else {
      // il y a un problème avec la requête
    }
  }
}

Code XML récupéré pour les exemples ci-dessous :
Exemple de code :
<root>
  <civilite/>
  <prenom>alias</prenom>
  <nom><![CDATA[dmc]]></nom>
  <adress>
    <ville><![CDATA[Lyon]]></ville>
  </adress>
</root>

Récupérer l'élément racine

Récupérer root

L'élément racine est la base du document XML. Il est unique et englobe tous les autres éléments, chez nous il se nomme root.
Pour le récupérer utilisez la propriété javascript documentElement.
Exemple de code :
var racine = xml.documentElement;
alert(racine.nodeName);
//root

Récupérer les fils

node.hasChildNodes

Pour savoir si l'élément a des fils, utilisez la méthode javascript hasChildNodes() qui renvoie un Boolean :
- true, j'ai des fils
- false, j'ai pas fils
Exemple de code :
var racine = xml.documentElement;
alert(racine.hasChildNodes());
// true ou false

Si vous utilisez firstChild ou lastChild vous devez faire le test hasChildNodes(). Mais si vous voulez juste récupérer les élément fils childNodes.length est suffisant.
Pour plus d'information voir Node

node.childNodes

L'atribut javascript childNodes permet de récupérer la liste des fils.
L'atribut childNodes renvoie une NodeList.
Exemple de code :
var racine = xml.documentElement;
alert(racine.childNodes.length);
//0 ou un nombre supérieur à 0


Pour plus d'information voir Node

Récupérer la valeur

La valeur texte d'un élément

Pour récupérer la valeur texte d'un élément vous devez tester le type (nodeType) de son premier fils (firstChild) pour savoir si c'est un objet Text ou un objet CDATASection (<![CDATA[ ... ]]>).
Exemple de code :
var racine = xml.documentElement;
for(var i = 0; i< racine.childNodes.length; i++){
  if(element.hasChildNodes()==true){
    var element = racine.childNodes[i];
    if(elementValue.nodeType==3 || elementValue.nodeType==4){
      alert(elementValue.nodeValue);
    }else{
      alert("c'est un noeux");
    }
  }
}

Pour plus d'information voir Node

Récupérer l'élément par son nom

node.getElementsByTagName

Pour récupérer un élément par son nom, vous devez utiliser la méthode getElementsByTagName().
La méthode getElementsByTagName() renvoie une NodeList.
Exemple de code :
var racine = xml.documentElement;
var tagnom = racine.getElementsByTagName("nom")
for(var i = 0; i< tagnom.length; i++){
    var element = racine.childNodes[i];
    alert(element.tagName);
}

Code XML :
Exemple de code :
<root>
    <identite>
      <prenom>alias</prenom>
      <nom>dmc 0</nom>
    </identite>
    <identite>
      <prenom>alias</prenom>
      <nom>dmc 1</nom>
    </identite>
</root>
Pour plus d'information voir Node

Récupérer un attribut

getAttribute & getAttributeNode

Vous pouvez pour récupérer soit un attribut soit une liste d'attribut.
Pour récupérer un attribut vous devez donc le ciblé avec son nom en utilisant la méthode getAttribute() ou getAttributeNode().
La différence entre getAttribute() et getAttributeNode(), c'est que la première renvoie un String et la deuxième un objet Attribut
Exemple de code :
var racine = xml.documentElement;
for(var i = 0; i< racine.childNodes.length; i++){
  var element = racine.childNodes[i].;
  var nom = element.nodeName;
  switch (nom){
    case "civilite" : alert(element.getAttribute("value"));
        break;
    case "adress" : alert(element.getAttribute("rue")); alert(element.getAttribute("numero"));
        break;
  }
}


La seconde méthode consiste à récupérer un tableau d'attributs, pour cela il faut utiliser attributes
qui renvoie un tableau NamedNodeMap contenant des Objet Attribut.
Exemple de code :
var racine = xml.documentElement;
for(var i = 0; i< racine.childNodes.length; i++){
  var element = racine.childNodes[i];
  var listAttribut = element.attributes;
  for(var h = 0;h<listAttribut.length;h++){
    var attribut = listAttribut[h];
    alert(attribut.name+"="+attribut.value);
  }
}

Exemples

Exemple

Dans cette exemple nous allons créer une fonction qui va parcourir l'arbe XML quelque soit sa profondeur.
Exemple de code :
/**/
function recuprecursif(xml){
  var result="";
  var racine = xml.documentElement;
  getFils(racine);
}
/**/
function getFils(xml){
  document.write( "<b>"+xml.nodeName +"</b> | Type "+ xml.nodeType+" | "+ xml.childNodes.length+ " fils");
  for(var i = 0; i<xml.childNodes.length; i++){
    var element = xml.childNodes[i];
    if(element.nodeType==1){
        getFils(element);
    }else if(element.nodeType==3 || element.nodeType==4){
        document.write(" valeur = "+ element.nodeValue);
    }
  }
}


Code XML :
Exemple de code :
<root>
    <identite><prenom>alias  0</prenom><nom>dmc  0</nom>
        <adress>
         <ville><![CDATA[Lyon]]></ville>
            <rue><![CDATA[20  Rue  de  l'effet  dmc]]></rue>
        </adress>
        </identite>
        
        
        
        <identite><prenom>alias  1  </prenom><nom>dmc  1</nom>
        <ville>
        
        
        <![CDATA[Lyon]]></ville>
        <rue><![CDATA[21  Rue  de  l'effet  dmc]]></rue>
      
      
        </identite>
</root>

Bug Firefox

Sous FireFox les espaces ou sauts de lignes font parties de l'arbe XML. Cela pose des problèmes, car on récupère des fils de type Text vide.

Pour remedier à ce bug :
Exemple de code :
function getFils(xml,nombre,bug){
  document.write( "<b>"+ xml.nodeName +"</b> | Type "+ xml.nodeType+" | "+ xml.childNodes.length+ " fils");
  for(var i = 0; i<xml.childNodes.length; i++){
    var element = xml.childNodes[i];
    if(element.nodeType==1){
        getFils(element);
    }else if(element.nodeType==3 || element.nodeType==4){
      if (!/S/.test(element.nodeValue)){
        //C'est un espace ou saut de ligne
      }else{
        document.write("valeur = "+element.nodeValue);
      }
    }
  }
}