Java API for XML Parsing (Jaxp)
Introduction
Java s'est vue adjoindre deux API spécialisées dans le traitement de document XML. Elles sont toutes les deux fournies dans un ensemble de package connus sous le nom de JAXP (Java API for XML Parsing). Si ces packages vous intéresse, sachez qu'ils ne sont pas directement inclus dans le JDK. Vous devez donc vous procurer JAXP sur le site de Sun Microsystem (http://java.sun.com/). En fait, Jaxp est pour le moment composé de deux archives Java : n'oubliez donc pas de faire correctement pointer la variable d'environnement CLASSPATH sur les deux archives, pour pouvoir utiliser ces packages.
Présentation du langage XML
XML (eXtensible Markup Language) est un langage d'échange et de structuration d'informations. Attention, ce qui pense encore qu'XML est un super HTML (HyperText Markup Language) se trompent. En effet, HTML est un langage de présentation, ce qui n'est nullement le cas pour XML.
En XML, le choix des tags est laissé libre à l'auteur du document. Normalement ces choix sont définis dans ce que l'on appelle une DTD (Document Type Definition). Cette DTD permet de valider une construction valide pour un document donné.
Pour ce qui est de la présentation des données contenues dans un document XML, on fait normalement appel à une feuille de style. Mais cet aspect sort complètement du cadre de ce cours. Si vous souhaitez acquérir des informations complémentaire sur le langage XML, vous pouvez toujours consulter le cours sur ce langage.
Parser du XML
Deux API sont principalement utilisées pour parser des documents XML
·
SAX (Simple API for XML) : cette API est définie par le groupe XML.org (http://www.xml.org). Elle est principalement basée sur un modèle évènementielles. A chaque élément syntaxique lut, une méthode est déclenchée. L'ensemble des méthodes déclenchées est définit via des interfaces prédéterminées.
·
Le modèle DOM (Document Object Model) : cette API, est quant à elle proposée par le W3C (World WideWeb Consortium : http://www.w3c.org). Cette API est basée sur un modèle objets prédéterminé. Cependant, il faut noter qu'il existe plusieurs niveaux de recommandations pour le DOM. JAXP n'est compatible qu'avec DOM-Level 1. Or actuellement (Décembre 2000), DOM-Level 2 est proposé et déjà supporté par tous les grand navigateurs (Netscape 6, IE 5).
Présentation de la librairie JAXP
La librairie JAXP (Java API for XML Parsing), proposée par SUN Micro system vous est proposée dans le but de vous aider à traiter des documents XML. Cette librairie propose des implémentations des deux modèles précédemment proposés : le modèle SAX et le modèle DOM.
Chacun des modèles est proposé, au sein de la librairie, sous forme de packages différents. Voici la structure de cette librairie.
Packages constitutifs de la librairie JAXP
javax.xml.parsers
org.w3c.dom
org.xml.sax
org.xml.sax.helpers |
Attention : cette librairie ne fait pas partie du JDK ! Vous pouvez la télécharger à partir du site de Sun. Toutes les classes sont stockées dans deux archives JAR. Il vous faut donc, pour pouvoir les utiliser, ne pas oublier de lier les archives à Java via la variable d'environnement CLASSPATH. Sans cette étape, rien ne compilera !
Le modèle SAX (Simple API for XML)
Ce premier exemple n'est en fait pas réellement utile en soit. Le seul intérêt qui justifie sa présence est qui permet de bien mettre en évidence le modèle "dirigé par les évènements". En effet, ce programme prend en entrée un document XML et génère en sortie un document XML équivalent, mais dont la mise en forme à été revue. En effet, les tags fermants sont indentés correctement par rapport aux tags ouvrants. De plus, les tags imbriqués seront au fur et à mesure indentés (décalé vers la droite) pour faire ressortir les niveaux d'imbrications.
import java.io.*;
import org.xml.sax.*;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
public class Echoing extends HandlerBase {
// Pour gérer l'indentation du document final.
private String indentString = " ";
private int indentLevel = 0;
// Démarrage de votre programme
public static void main (String argv []) {
if (argv.length != 1) {
System.err.println ("Usage: cmd filename");
System.exit(-1);
}
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser saxParser = factory.newSAXParser();
saxParser.parse( new File(argv [0]), new Echoing() );
} catch (Throwable t) {
t.printStackTrace ();
}
System.exit(0);
}
/////////////////////////////////////////////////////////////
// Les gestionnaires d'évènements SAX ///////////////////////
/////////////////////////////////////////////////////////////
public void startDocument () throws SAXException {
System.out.println("START DOCUMENT");
System.out.println("<?xml version='1.0' encoding='UTF-8'?>");
}
public void endDocument () throws SAXException {
System.out.println("END DOCUMENT");
if (indentLevel > 0) System.out.println("AIEEEE");
}
public void startElement (String name, AttributeList attrs)
throws SAXException {
tabs();
System.out.print("<"+name);
if (attrs != null) {
for (int i = 0; i < attrs.getLength (); i++) {
System.out.println();
tabs();
System.out.print(" ");
System.out.print(attrs.getName (i));
System.out.print(" = \"");
System.out.print(attrs.getValue (i));
System.out.print("\"");
}
}
if (attrs.getLength() > 0) { System.out.println(""); tabs(); }
System.out.println(">");
indentLevel++;
}
public void endElement (String name) throws SAXException {
indentLevel--;
tabs();
System.out.println("</"+name+">");
}
public void characters (char buf [], int offset, int len)
throws SAXException {
String s = new String(buf, offset, len);
if (!s.trim().equals("")) {
tabs();
System.out.println(s);
}
}
/////////////////////////////////////////////////////////////
// Fonctions utilitaires ////////////////////////////////////
/////////////////////////////////////////////////////////////
private void tabs() {
for(int i=0;i<indentLevel;i++) {
System.out.print(indentString);
}
}
} |
Ce qui faut retenir de cet exemple : votre classe étend une classe de base sur laquelle une certain nombre de méthodes sont prédéfinies, mais ne font rien. Votre travail consiste à redéfinir ces méthodes pour réagir aux conditions (aux événements) souhaitées. Les méthodes principales de la classe HandlerBase sont :
public void startDocument() : |
est invoquée au commencement du document. |
public void endDocument() : |
de même mais à la fin du document. |
public void startElement (String name, AttributeList attrs) : |
est invoquée lors de la lecture d'un tag ouvrant. |
public void endElement (String name) : |
est invoquée lors de la lecture d'un tag
fermant. |
public void characters (char buf [], int offset, int len) : |
permet de récupérer les données des tags. |
Le modèle DOM
Le Document Object Model (DOM) permet un mode programmation réellement différent de celui proposé par SAX. En effet, cette fois-ci, le document va d'abord être complètement traité avant que vous puissiez faire quoi que se soit. Le but de cette API est de générer un arbre d'éléments représentant parfaitement le document XML originel. Nous allons aussi voir que vous pouvez, via cette API, directement travailler au niveau de l'arborescence d'objets pour générer un nouveau document XML.
Générer un nouveau document via DOM
Dans cet exemple, nous allons voir comment créer un nouveau document XML, ce à partir de données de provenance quelconque. En effet, le modèle DOM propose un certain nombre de méthodes permettant d'accrocher de nouvelles données dans un arbre d'éléments (même nouvellement crée).
import java.io.*;
import com.sun.xml.tree.*;
import org.w3c.dom.*;
public class DomTest {
public static void main(String args[]) {
try {
Document document = new XmlDocument();
//-Génération de l'arbre de noeudst--------------------------------
Element root = document.createElement("PERSONNE");
Element first = document.createElement("FIRSTNAME");
Element second = document.createElement("LASTNAME");
Text firstTxt = document.createTextNode("Dominique");
Text seconTxt = document.createTextNode("Liard");
document.appendChild(root);
root.appendChild(first);
root.appendChild(second);
first.appendChild(firstTxt);
second.appendChild(seconTxt);
root.setAttribute("Machin", "truc");
//-Affichage du document XML source--------------------------------
((XmlDocument)document).write(System.out);
} catch(Exception e) {
e.printStackTrace();
}
}
} |
Compilez ce programme et exécutez-le. Si tous se passe bien, vous devriez observer l'affichage suivant.
<?xml version="1.0" encoding="UTF-8"?>
<PERSONNE Machin="truc">
<FIRSTNAME>Dominique</FIRSTNAME>
<LASTNAME>Liard</LASTNAME>
</PERSONNE> |
Manipuler un document existant via DOM
Mais nous pouvons aussi manipuler un document déjà existant. Regardez bien l'exemple suivant. Il charge initialement un document XML, et en construit une représentation objets via DOM. Ensuite, une exploration d'un graphe est réalisée afin de trouver le tag <FIRSTNAME>. Ce tag est alors modifié en mettant la donnée du tag en Majuscules. Au final, le document est affiché à l'écran.
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import com.sun.xml.tree.*;
public class Modify {
public static void main(String args[]){
if (args.length == 0) {
System.err.println("Usage : java Modify xmlFileName");
System.exit(-1);
}
try {
//-Chargement du document-------------------------------------
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
FileInputStream fis = new FileInputStream(new File(args[0]));
Document doc = builder.parse(fis);
//-Modification du document------------------------------------
Node personne = doc.getChildNodes().item(0);
System.out.println(personne.getNodeName());
Node firstName = personne.getChildNodes().item(1);
System.out.println(firstName.getNodeName());
Text txt = (Text)firstName.getChildNodes().item(0);
System.out.println(txt.getData());
txt.setData(txt.getData().toUpperCase());
System.out.println("--------------------");
//-Affichage du résultat---------------------------------------
((XmlDocument)doc).write(System.out);
} catch(Exception e) {
e.printStackTrace();
}
}
} |
Quelques méthodes fort utiles
Interface Document
Text createTextNode (): Création d'un nouveau nœud de
tag
Element
createElement (): Création d'un nouveau nœud de texte
Attr createAttribute() :
Création d'un nouvel attribut
Interface Node
String getNodeName(): Récupération du nom du nœud de
tag
String getNodeValue():
Récupération de la valeur du nœud de tag
void setNodeValue(String val):
Affectation de la valeur du nœud de tag
Node getParentNode():
Récupération du nœud parent
NodeList getChildNodes(): Récupération de la liste des nœud
enfants
Node
getPreviousSibling() :Récupération du nœud directement précédent
Node getNextSibling():
Récupération du nœud directement suivant
Node appendChild(Node e):Accrocher un nœud à l'arbre
Interface NodeList
int getLength() :
Retourne le nombre de nœuds contenu
Node item(int indice).: Retrouve le indiceième nœud de la liste
Conclusion
Nous avons donc vu qu'il était possible de traiter, via la librairie JAXP, des documents XML par vos programmes Java. Pour ce faire, deux API (à vocation différente) vous sont proposées. La premier, SAX, permet de développer un code travaillant lors de l'acquisition des données. La seconde, DOM, permet la manipulation d'un arbre d'éléments : cet arbre est en fait une représentation équivalente au fichier XML, mais sa manipulation via Java en sera grandement simplifiée. Il doit être clair qu'il existe un lien entre ces deux APIs. En effet, l'API DOM est codée à partir de l'API SAX.
...
|