I. Présentation

XMLBeans est un outil qui permet de faire du databinding Java/XML.

Il a été initié en 2003 par David Bau, de BEA, puis est devenu open source puisque cédé à la fondation Apache.

On peut télécharger la librairie sur http://xmlbeans.apache.org/

La version actuelle est 2.3.0.

Elle offre la possibilité de mapper un document XML en objets Javabeans.

Au lieu de parcourir un arbre DOM ou de faire de l'évènementiel avec SAX par exemple, on passe par des getters et setters.

On peut générer des fichiers XML à partir de classes Java, ou inversement, générer des objets Java (POJOs) à partir de fichiers XML.

Les outils utilisés dans cet article sont :

  • Eclipse 3.4 Ganymede
  • Java 1.5
  • Altova XMLSpy version 2008
  • XMLBeans 2.3.0
  • Saxon 8.8 (fichier saxonb8-8j.zip), une implémentation open-source de XSLT 2.0 et XPath 2.0, et XQuery 1.0

II. Schéma XML et DTD

Il est nécessaire de faire quelques rappels rapides.

  • Une DTD (Document Type Definition) : une DTD permet de vérifier qu'un document XML est valide. Il est valide s'il est conforme aux règles sémantiques définies dans la DTD.
  • Un schéma XML : aussi appelé XSD (XML Schema Definition), il est une alternative aux DTDs.

II-A. Validation via un Schéma XML

Vehicule1.xml
TéléchargerCacher/Afficher le codeSélectionnez

A l'aide de XMLSpy (ou tout simplement d'un browser), on peut valider le fichier XML, par rapport au schéma XML suivant.

Vehicule1.xsd
TéléchargerCacher/Afficher le codeSélectionnez

II-B. Validation via une DTD

Vehicule2.xml
TéléchargerCacher/Afficher le codeSélectionnez
Vehicule2.dtd
TéléchargerCacher/Afficher le codeSélectionnez

Les schémas XML présentent plusieurs avantages par rapport aux DTDs :

  • une syntaxe XML
  • possibilité de spécifier les types des données
  • espace de nommage (namespace), ce qui implique que les règles pour définir certains éléments seront à un certain endroit tandis que les règles pour valider les règles pour définir d'autres éléments seront à un autre endroit.

III. Exemple

Pour ce tutoriel, je vais prendre comme exemple de base le cas d'un parc automobile qu'on peut découper de la façon suivante :

parcAuto.xml
TéléchargerCacher/Afficher le codeSélectionnez

On peut automatiquement créer le Schéma XML grâce à XMLSpy :

Image non disponible

parcAuto.xsd
TéléchargerCacher/Afficher le codeSélectionnez

IV. Génération des classes

Pour utiliser XMLBeans, il faut définir la variable d'environnement XMLBEANS_HOME, elle pointe vers le répertoire d'installation de XMLBeans.

On va créer les classes Java à partir du Schéma XML.

Pour cela, il y a 2 façons de faire. Soit on passe par l'utilitaire SCOMP, soit on utilise une tâche Ant xmlbean.

IV-A. L'utilitaire SCOMP (Schema Compiler)

Dans une fenêtre DOS, on tape la commande scomp :

Image non disponible

Après avoir ajouter XMLBEANS_HOME/bin dans le PATH (set PATH=%PATH%;%XMLBEANS_HOME%\bin\), on peut taper la commande suivante :

 
Sélectionnez
1.
>scomp -src src -javasource 1.5 -out parcAuto.xsd

Image non disponible

Note: pour éviter d'avoir un java.io.IOException, il faut modifier le script scomp.cmd en changeant la ligne suivante :

 
Sélectionnez
1.
java -classpath "%cp%" org.apache.xmlbeans.impl.tool.SchemaCompiler %*

par

 
Sélectionnez
1.
%JAVA_HOME%/bin/java -classpath "%cp%" org.apache.xmlbeans.impl.tool.SchemaCompiler %*

On obtient la hiérachie suivante :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
    D:\tutorielXMLBeans\  
    D:\tutorielXMLBeans\parcAuto.xsd  
    D:\tutorielXMLBeans\xmltypes.jar  (contient les classes compilées et des fichiers XSB nécessaires à XMLBeans)  
    D:\tutorielXMLBeans\src (contient les interfaces et classes générées)  
    D:\tutorielXMLBeans\src\noNamespace (pas de namespace dans le Schema)  
    D:\tutorielXMLBeans\src\noNamespace\CouleurDocument.java  
    D:\tutorielXMLBeans\src\noNamespace\MarqueDocument.java (type complexe Marque)  
    D:\tutorielXMLBeans\src\noNamespace\NombreDocument.java  
    D:\tutorielXMLBeans\src\noNamespace\NomDocument.java  
    D:\tutorielXMLBeans\src\noNamespace\ParcautomobileDocument.java (element racine Parcautomobile)  
    D:\tutorielXMLBeans\src\noNamespace\PuissanceDocument.java  
    D:\tutorielXMLBeans\src\noNamespace\VehiculeDocument.java  (type complexe Vehicule)  
    D:\tutorielXMLBeans\src\noNamespace\impl  
    D:\tutorielXMLBeans\src\noNamespace\impl\CouleurDocumentImpl.java  
    D:\tutorielXMLBeans\src\noNamespace\impl\MarqueDocumentImpl.java  
    D:\tutorielXMLBeans\src\noNamespace\impl\NombreDocumentImpl.java  
    D:\tutorielXMLBeans\src\noNamespace\impl\NomDocumentImpl.java  
    D:\tutorielXMLBeans\src\noNamespace\impl\ParcautomobileDocumentImpl.java  
    D:\tutorielXMLBeans\src\noNamespace\impl\PuissanceDocumentImpl.java  
    D:\tutorielXMLBeans\src\noNamespace\impl\VehiculeDocumentImpl.java

Il faut inclure le jar xmltypes.jar dans le CLASSPATH.

IV-B. Tâche Ant xmlbean

Une tâche ANT existe pour compiler un fichier XSD en classe XMLBeans. Elle permet d'obtenir un fichier JAR mais aussi le code source.

build.xml
TéléchargerCacher/Afficher le codeSélectionnez

Après lancement de la tâche, on obtient la hiérarchie suivante dans Eclipse :

Image non disponible

L'archive tuto.jar contient les fichiers XSB et est à mettre dans le build path du projet :

Image non disponible

V. Génération d'un fichier XML

Grâce aux classes engendrées par XMLBeans, on peut manipuler les différents éléments XML comme des objets java Beans.

Chaque interface possède une classe factory avec une méthode statique newInstance() pour créer une instance du type de la classe.

Les valeurs fixes sont représentées avec des énumérations.

On valide par rapport au schéma XML l'instance nouvellement créée avec la méthode validate() de l'interface XmlObject.

GenerationXML.java
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
package com.developpez.tutoriel;  
  
import java.io.File;  
import java.io.IOException;  
  
import noNamespace.ParcautomobileDocument;  
import noNamespace.CouleurDocument.Couleur;  
import noNamespace.MarqueDocument.Marque;  
import noNamespace.NomDocument.Nom;  
import noNamespace.ParcautomobileDocument.Parcautomobile;  
import noNamespace.PuissanceDocument.Puissance;  
import noNamespace.VehiculeDocument.Vehicule;  
import noNamespace.VehiculeDocument.Vehicule.Modele;  
  
import org.apache.xmlbeans.XmlOptions;  
  
public class GenerationXML {  
      
     public static void main(String[] args) throws IOException  
      {            
            //parc est une instance du document XML  
            ParcautomobileDocument parc = ParcautomobileDocument.Factory.newInstance();  
              
            //ajout d'un tag Parcautomobile au document XML  
            Parcautomobile parcautomobile = parc.addNewParcautomobile();  
              
            // ajout d'un Vehicule au parc automobile  
            Vehicule vehicule1 = parcautomobile.addNewVehicule();                         
            vehicule1.setModele(Modele.COUPE);  
              
            //Vehicule de modèle COUPE, 1ère marque   
            Marque marque1 = vehicule1.addNewMarque();  
            marque1.setNom(Nom.RENAULT);  
              
            Puissance puissance1 = Puissance.Factory.newInstance();           
            puissance1.setChevaux((byte)8);  
            puissance1.setVitessemax((short)280);             
            marque1.setPuissance(puissance1);     
            marque1.setNombre((byte)18);  
            marque1.setCouleur(Couleur.NOIR);  
              
            //Vehicule de modèle COUPE, 2ème marque   
            Marque marque2 = vehicule1.addNewMarque();  
            marque2.setNom(Nom.PEUGEOT);  
              
            Puissance puissance2 = Puissance.Factory.newInstance();           
            puissance2.setChevaux((byte)11);  
            puissance2.setVitessemax((short)320);             
            marque2.setPuissance(puissance2);     
            marque2.setNombre((byte)10);  
            marque2.setCouleur(Couleur.ROUGE);  
                                  
            // ajout d'un Vehicule au parc automobile  
            Vehicule vehicule2 = parcautomobile.addNewVehicule();                         
            vehicule2.setModele(Modele.BERLINE);  
              
            //Vehicule de modèle COUPE, 1ère marque   
            Marque marque3 = vehicule2.addNewMarque();  
            marque3.setNom(Nom.MERCEDES);  
              
            Puissance puissance3 = Puissance.Factory.newInstance();           
            puissance3.setChevaux((byte)10);  
            puissance3.setVitessemax((short)330);             
            marque3.setPuissance(puissance3);     
            marque3.setNombre((byte)9);  
            marque3.setCouleur(Couleur.GRIS);  
              
            //Vehicule de modèle COUPE, 2ème marque   
            Marque marque4 = vehicule2.addNewMarque();  
            marque4.setNom(Nom.BMW);  
              
            Puissance puissance4 = Puissance.Factory.newInstance();           
            puissance4.setChevaux((byte)12);  
            puissance4.setVitessemax((short)300);             
            marque4.setPuissance(puissance4);     
            marque4.setNombre((byte)7);  
            marque4.setCouleur(Couleur.BLEU);  
              
            // Validation de l'instance du schema XML  
              boolean estValide = parc.validate();  
              
              if (! estValide){  
                   System.err.println("Attention, cette instance du schema n'est pas valide ! ");  
                   return;  
              }  
              
            XmlOptions opts = new XmlOptions();  
            //cette option permet d'indenter le code   
            opts.setSavePrettyPrint();  
              
            System.out.println(parc.xmlText(opts));  
            parc.save(new File ("d:/parcAuto.xml"), opts);      
      }  
}

On obtient en sortie un fichier XML parcAuto.xml identique au précédent.

VI. Parsing d'un fichier XML

Et inversement, il est possible de parcourir un fichier XML de façon totalement objet.

On utilise la méthode parse() de l'interface ParcautomobileDocument pour charger le fichier et ensuite le parcourir.

ParseXML.java
TéléchargerCacher/Afficher le codeSélectionnez

Sortie de la console :

 
TéléchargerCacher/Afficher le codeSélectionnez

VII. L'interface XMLCursor

L'interface XmlCursor fournit une navigation efficace dans un arbre XML, à la manière d'un curseur en PL/SQL.

Le curseur représente un endroit spécifique (noeud) dans le document XML.

Dans l'API XMLCursor, un document XML est constitué par des tokens.

Concrètement, un token est soit un type d'attribut, soit un début d'élément, soit une fin d'élément etc.

Exemple: on peut insérer un nouveau modèle de véhicule au niveau de l'élément racine <parcautomobile> , au tout début.

InsertionXML.java
TéléchargerCacher/Afficher le codeSélectionnez

Résultat de l'insertion :

 
TéléchargerCacher/Afficher le codeSélectionnez

VIII. XQuery

Pour une recherche avancée dans le document XML, on doit passer par Xquery.

XQuery est à XML ce que SQL est aux bases de données.

Si on veut récupérer dans le document XML le nombre de Peugeot dans le parc automobile, on peut naviguer dans l'arbre pour aller se positionner directement sur le sous-élément <nombre> de l'élément <marque> , lui-même sous-élément de l'élément <vehicule modele="coupe">.

La méthode execQuery(queryExpression) de l'interface XmlCursor prend en paramètre une expression Xquery.

Note: il est nécessaire d'installer la librairie Saxon (processor XSLT et XQuery).
En effet, pour des raisons d'incompatibilités de licences, cette librairie n'est malheureusement pas incluse dans XMLBeans.

InsertionXML.java
TéléchargerCacher/Afficher le codeSélectionnez

Résultat :

 
TéléchargerCacher/Afficher le codeSélectionnez

Note: il existe une autre interface graphique, beaucoup plus simple que XMLSpy, pour rapidement tester les requêtes XQuery, à savoir XQuisitor.

IX. XPath

On peut passer par des expressions XPath, que l'on donne en paramètre de la méthode selectPath(String).

Elle retourne des sélections.

Et on navigue ensuite à l'aide de la méthode toNextSelection(), pour itérer à travers les sélections.

Exemple : afficher tous les noms de marque de vehicules dans le fichier XML.

XpathXML.java
TéléchargerCacher/Afficher le codeSélectionnez

Résultat de la recherche :

 
TéléchargerCacher/Afficher le codeSélectionnez

X. Liens