Parcours de fichiers XML avec XPath
Date de publication : 09/12/2006
Par
ZedroS
L'article qui suit est une introduction à l'utilisation de la technologie XPath depuis Java, grâce aux librairies JDom et Jaxen.
I. Introduction
II. Présentation
II-A. Qu'est ce que XPath ?
II-B. Solutions Java pour XPath
II-C. Environnement requis
III. Principe de fonctionnement
III-A. Vue d'ensemble
III-B. La syntaxe XPath
III-C. XPath appliqué au Java
IV. Exemple de mise en oeuvre
IV-A. Le fichier XML considéré
IV-B. La classe principale
V. Conclusion
I. Introduction
XPath permet de parcourir un fichier XML d'une façon à la fois simple et puissante. De la sorte, en peu de temps, un développeur peut rapidement et aisément extraire les informations qui l'intéressent, même dans un document qui en comporte bien plus. On peut par exemple :
- récupérer le contenu d'une balise précise
- récupérer du contenu en fonction de la valeur d'un attribut d'une balise
- récupérer un ensemble de balises avec leur contenu et les parcourir
C'est ce que nous allons détailler dans ce tutoriel. Après une courte présentation d'XPath, de quelques solutions Java existantes, nous passerons rapidement à la pratique avec des explications et exemples utilisant JDom et Jaxen. Pour finir, vous trouverez des codes sources et d'autres liens intéressants en fin d'article.
II. Présentation
II-A. Qu'est ce que XPath ?
Pour cela, rien de tel que de parcourir la
XML (XPath), qui nous dit :
| XPath est un langage avec une syntaxe non XML, permettant d'adresser les différents noeuds ou groupes de noeuds particuliers d'un document XML. XPath voit le document XML comme un arbre de noeuds, qu'il permet de parcourir selon des axes (fils, parent, ancêtre, descendant, ...) et en en sélectionnant les noeuds par leur nom. Les expressions XPath permettent également de représenter des chaînes de caractères, des nombres et des booléens.
XPath est intensément utilisé par d'autres langages et technologies XML, tels que XSLT, les W3C XML Schema, XLink, XForms...
|
II-B. Solutions Java pour XPath
| Comme souvent en Java, le choix est vaste. Voici quelques unes des APIs XPath disponibles pour la plateforme Java :
- APIs standard : Depuis J2SE 5.0 (Tiger), l'API standard contient le package javax.xml.xpath, qui permet de travailler avec XPath.
- Jaxen : Cette API est capable d'évaluer des expressions XPath sur de nombreux modèles (JDOM, DOM4J ou encore DOM).
- Saxon : Pour finir, on peut citer Saxon, qui a la particularité de permettre de travailler avec la spécification XPath 2.0.
|
Pour cet article, le choix s'est porté Jaxen, et plus précisément l'implémentation que l'on trouve dans JDom.
II-C. Environnement requis
|
Comme précisé plus haut, les librairies utilisées sont JDom et Jaxen. Voici les jars dont on aura besoin :
- jdom.jar : définition des interfaces
- jaxen-core.jar : pour le parsing
- jaxen-jdom.jar : implémentation d'XPath
- saxpath.jar : pour construire le fichier Dom
|
Pour obtenir ces jars, rien de plus simple : il suffit de se rendre sur le site de
Jdom. Dans
Downloads/binaries vous avez le lien pour Jdom 1.0. Téléchargez alors l'ensemble Jdom au format de votre choix puis décompressez le. On y trouve :
- sous \build : jdom.jar
- sous \lib : les autres jars qui nous intéressent, à savoir jaxen-core.jar, jaxen-dom.jar et saxpath.jar
III. Principe de fonctionnement
III-A. Vue d'ensemble
La bibliothèque JDom propose une interface qui définit une façon d'utiliser XPath en Java pour parcourir des fichiers XML. Le jar jaxen-jdom implémente cette interface.
Le fonctionnement est le suivant : le document est entièrement parsé et mis en mémoire, via un Document JDom. A partir de ce document, on va appliquer des chemins XPath pour trouver les éléments qui nous concernent. Ces chemins XPath permettent d'aller à l'essentiel, en évitant de décrire le chemin exact suivi. On va pouvoir demander de chercher tel attribut ou telle balise à partir de l'endroit courant ou sur l'ensemble du Document.
Bien sûr, ce parcours initial, et surtout la constitution du Document, n'est pas l'approche la plus rapide (voir SAX pour cela).
Par contre, côté développeur, le gain de temps dans le parcours du fichier XML est considérable. Plus besoin de chercher le détail de l'enchaînement des balises, on va directement à l'essentiel !
III-B. La syntaxe XPath
XPath propose en fait un langage de localisation, dont les éléments de base sont les suivants :
Elément syntaxique |
Type de chemin |
Exemples de chemin |
Exemples de chemin répondant au chemin indiqué à gauche |
balise |
Nom d'élément |
hopital |
<hopital>…</hopital> |
/ |
Sépare enfants directs |
hopital/personne |
<hopital>
<personne>…</personne>
</hopital>
|
// |
Descendant |
hopital//relations |
----
|
//nom |
|
<hopital>
<pensionnaires>
<patient>
<relations>...</relations>
</patient>
</hopital>
|
----
|
<hopital>
<personne>
<nom></nom>
</personne>
<hopital>
=> recherche n'importe où dans le schéma
|
|
* |
"wildcard" |
*/title |
<bla><title>..</title> ou <bli><title>...</title> |
| |
opérateur "ou" |
|
<title>...</title> ou <head> ...</head>
|
----
|
(tous les éléments: les enfants, la racine et les attributs de la racine)
|
|
. |
élément courant |
. |
|
../ |
élément supérieur |
../problem |
<project> |
@ |
nom d'attribut |
|
<xyz id="test">...</xyz>
|
----
|
<project id="test" ...> ... </project>
|
|
@attr='type' |
Valeur d'attribut |
list[@type='ol'] |
<list type="ol"> ...... </list> |
Pour plus de renseignements, je vous enjoints à regarder cet excellent pdf :
Introduction technique à XSLT, dont le tableau ci-dessus est fortement inspiré (avec l'accord des auteurs de ce document).
Le résultat d'une recherche peut prendre plusieurs formes :
la valeur du premier noeud répondant à l'expression,
le premier nœud répondant à l'expression,
l'ensemble des nœuds répondant à la requête.
Par nœud, il faut entendre l'emplacement d'une balise précise dans le fichier XML. Ainsi, à l'aide du « . » ou du «..», il est également possible de faire une recherche à partir du ou des nœuds trouvés dans une recherche précédente.
Comme vous pouvez le constater, la puissance d'expression de ce langage est conséquente.
III-C. XPath appliqué au Java
Il faut dans un premier temps construire le document DOM :
SAXBuilder sxb = new SAXBuilder ();
org.jdom.Document document = sxb.build (new File (" exempleXml.xml " ));
racine = document.getRootElement ();
|
Il faut ensuite déclarer le chemin à chercher, on procède ainsi :
XPath xpa = XPath.newInstance (" chemin " );
|
On applique alors ce chemin à un nœud de notre choix, par exemple la racine. Nous pouvons choisir soit :
- d'obtenir la valeur retournée :
String retour = xpa.valueOf (currentNode);
|
- d'obtenir le premier nœud répondant à notre requête :
Element monNoeud = (Element) xpa.selectSingleNode (racine);
|
- d'obtenir tous les nœuds répondant à notre requête :
List listeNoeuds = xpa.selectNodes (racine);
|
IV. Exemple de mise en oeuvre
Un exemple vaut mieux que de nombreux discours, voyons donc ce que cela donne.
IV-A. Le fichier XML considéré
Pour cela, nous allons nous baser sur un fichier XML un peu complexe, construit ainsi :
hopital.xml |
<? xml version="1.0" encoding="UTF-8"? >
< hopital >
< personne id = " idPersonne1 " >
< nom > Hugo< / nom >
< prenom > Victor< / prenom >
< / personne >
< personne id = " idPersonne2 " >
< nom > Victor< / nom >
< prenom > Paul Emile< / prenom >
< / personne >
< personne id = " idPersonne3 " >
< nom > Kontz< / nom >
< prenom > Dean R.< / prenom >
< / personne >
< personne id = " idPersonne4 " >
< nom > Sand< / nom >
< prenom > Georges< / prenom >
< / personne >
< personne id = " idPersonne5 " >
< nom > Clark< / nom >
< prenom > Marie Higgins< / prenom >
< / personne >
< personne id = " idPersonne6 " >
< nom > Weis< / nom >
< prenom > Margaret< / prenom >
< / personne >
< personne id = " idPersonne7 " >
< nom > Fielding< / nom >
< prenom > Helen< / prenom >
< / personne >
< personne id = " idPersonne8 " >
< nom > de Troyes< / nom >
< prenom > Chrétien< / prenom >
< / personne >
< pensionnaires >
< patient personneId = " idPersonne3 " >
< filiation >
< parent personneId = " idPersonne1 " type = " naturel " >
< contact type = " journalier " ddebut = " 1989/02/16 "
dfin = " 2001/12/21 " > Enfance< / contact >
< contact type = " épisodique " ddebut = " 2001/12/22 "
dfin = " .. " > Divorce des parents, baisse des contact
< / contact >
< / parent >
< parent personneId = " idPersonne4 " type = " naturel " >
< contact type = " régulier " ddebut = " 1989/02/16 "
dfin = " 2001/12/21 " > Enfance de Dean R.< / contact >
< contact type = " aucun " ddebut = " 2001/12/22 "
dfin = " .. " >
Rupture entre les parents, Dean R. ne parle plus à sa mère.
< / contact >
< / parent >
< parent personneId = " idPersonne7 " type = " tuteur " / >
< contact type = " fréquent " ddebut = " 2002/02/12 "
dfin = " .. " > Nouveau tuteur légal< / contact >
< / parent >
< / filiation >
< internements >
< sejour ddebut = " 2002/01/11 " dfin = " 2002/01/14 " >
Crise d'appendicite< / sejour >
< / internements >
< / patient >
< patient personneId = " idPersonne2 " >
< filiation >
< parent personneId = " idPersonne1 " type = " naturel " >
< contact type = " épisodique " ddebut = " 1985/03/21 "
dfin = " .. " > Père souvent en déplacement< / contact >
< / parent >
< parent personneId = " idPersonne5 " type = " naturel " >
< contact type = " journalier " ddebut = " 1985/03/21 "
dfin = " 1999/08/11 " > Paul Emile vit chez sa mère< / contact >
< contact type = " aucun " ddebut = " 1999/08/12 "
dfin = " .. " > Décès< / contact >
< / parent >
< / filiation >
< internements >
< sejour ddebut = " 1998/03/22 " dfin = " 1998/04/12 " >
Crise de rire à répétition< / sejour >
< / internements >
< / patient >
< patient personneId = " idPersonne6 " >
< filiation >
< parent personneId = " idPersonne8 " type = " naturel " >
< contact type = " régulier " ddebut = " 1982/12/30 "
dfin = " .. " > RAS< / contact >
< / parent >
< parent personneId = " idPersonne4 " type = " naturel " >
< contact type = " régulier " ddebut = " 1982/12/30 "
dfin = " .. " > RAS< / contact >
< / parent >
< / filiation >
< internements >
< sejour ddebut = " 1998/03/22 " dfin = " 1998/03/25 " > Bras cassé
< / sejour >
< / internements >
< / patient >
< / pensionnaires >
< / hopital >
|
Je précise que ce fichier n'est qu'à but purement éducatif. Il ne représente pas un exemple de bonne construction XML, notamment au niveau des balises <personne>.
Ce fichier est disponible
là.
IV-B. La classe principale
Main.java |
package org.zedros.xpathxmlreader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
@author
public class ExempleXPath {
private Element racine;
public ExempleXPath () {
}
void parse (File _FilePath) {
org.jdom.Document document = null ;
try {
SAXBuilder sxb = new SAXBuilder ();
document = sxb.build (_FilePath);
} catch (IOException e) {
System.out.println (" Erreur lors de la lecture du fichier "
+ e.getMessage () );
e.printStackTrace ();
} catch (JDOMException e){
System.out.println (" Erreur lors de la construction du fichier JDOM "
+ e.getMessage () );
e.printStackTrace ();
}
try {
Element racine = document.getRootElement ();
XPath xpa = XPath.newInstance (" //patient " );
List results = xpa.selectNodes (racine) ;
Iterator iter = results.iterator () ;
Element noeudCourant = null ;
String personneId = null ;
while (iter.hasNext ()){
noeudCourant = (Element) iter.next ();
xpa = XPath.newInstance (" ./@personneId " );
personneId = xpa.valueOf (noeudCourant);
xpa = XPath.newInstance (" //personne[@id=' " + personneId + " '] " );
noeudCourant = (Element) xpa.selectSingleNode (noeudCourant);
xpa = XPath.newInstance (" ./nom " );
System.out.println (" Valeur : " + xpa.valueOf (noeudCourant));
}
} catch (JDOMException e) {
System.out.println (" Erreur JDOM " + e.getMessage () );
e.printStackTrace ();
}
}
}
|
Ce fichier est téléchargeable
là.
Et enfin, la classe Main pour lancer tout ça :
ExempleXPath |
package org.zedros.xpathxmlreader;
import java.io.File;
import org.jdom.JDOMException;
@author
public class Main {
public Main () {
}
@param
public static void main (String[] args) throws JDOMException {
File entryFile = new File (" d:/Java/xml/hopital01.xml " );
ExempleXPath exemple = new ExempleXPath ();
exemple.parse (entryFile);
}
}
|
Ce fichier est téléchargeable
là.
V. Conclusion
J'espère que ce petit exemple vous a convaincu de l'intérêt et de la faisabilité de la mise en oeuvre d'XPath via du code Java. Pour ma part, j'utilise désormais cette approche dès que je dois parcourir du XML sans avoir de contraintes de performances.
Vous trouverez ci-contre les sources de cet article ainsi que d'autres ressources intéressantes sur les technologies Java, XML et XPath.
Pour finir, vous pouvez toujours vous appuyer sur les forums de developpez.com si vous avez d'autres questions : forums XML et forums Java.
|
|
Copyright © 2006 ZedroS.
Aucune reproduction, même partielle, ne peut être faite
de ce site ni de l'ensemble de son contenu : textes, documents, images, etc.
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à
trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.