L'exploitation d'un document XML à partir du modèle d'objet de document demeure relativement simple.
L'ouverture d'un document XML demeure le préalable obligatoire à l'utilisation du modèle d'objet DOM. Le paquetage javax.xml.parsers contient deux classes particulièrement importantes, puisqu'elles permettent de créer et de charger une source XML.
DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); DocumentBuilder analyseur = fabrique.newDocumentBuilder();
Des caractéristiques et certaines propriétés (validation du document XML par rapport à sa DTD, prise en compte des espaces de noms et des inclusions XML, développement des références d'entités, fusion des noeuds CDATA adjacents, élimination des espaces blancs non-indispensables dans les éléments et abandon des commentaires) peuvent être précisées lors de l'instanciation de la classe DocumentBuilderFactory.
DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); fabrique.setValidating(true); fabrique.setNamespaceAware(true); fabrique.setXIncludeAware(true); fabrique.setExpandEntityReferences(true); fabrique.setCoalescing(false); fabrique.setIgnoringElementContentWhitespace(true); fabrique.setIgnoringComments(false); DocumentBuilder analyseur = fabrique.newDocumentBuilder();
La fabrique DocumentBuilderFactory transmet toute la configuration aux analyseurs DOM qu'elle crée à l'aide de la méthode newDocumentBuilder().
Désormais, l'objet DocumentBuilder est prêt à produire un document XML à partir de différentes sources d'entrées à fournir à sa méthode d'instance parse().
Document document = analyseur.parse("fichier.xml"); //ou BufferedReader br = new BufferedReader(new FileReader("fichier.xml")); InputSource source = new InputSource(br); Document document = analyseur.parse(source); //ou URL url = new URL("http://laltruiste.com/coursjava/exemples/employes.xml"); BufferedInputStream bis = new BufferedInputStream(url.openStream()); Document document = analyseur.parse(bis); //ou Document document = analyseur.parse( "http://laltruiste.com/coursjava/exemples/employes.xml");
L'exploration du document XML s'effectue en se déplaçant dans l'arborescence, de noeud en noeud, à l'aide des nombreuses méthodes et attributs proposées par le DOM.
L'emplacement du document XML, s'il n'a pas été créé par la méthode DOMImplementation.createDocument, devrait être obtenu par la méthode getDocumentURI(). L'adresse URI peut aider à résoudre des adresses relatives au sein du document, comme les références vers une DTD externe, un schéma XML ou une feuille de style XSLT.
String uri = document.getDocumentURI();
Un document XML contient un prologue qui fournit certaines informations à son propos :
String version = document.getXmlVersion(); String encodage = document.getXmlEncoding(); if(document.getXmlStandalone()) System.out.println("Le document est autonome !"); else System.out.println("Le document n'est pas autonome !");
L'encodage de caractères employé au moment de l'analyse du document peut différer de celui déclaré dans le prologue. La méthode getInputEncoding() fournit cette information.
String encodage_analyse = document.getInputEncoding()
La configuration du DOM pour le document courant présente divers paramètres, identiques aux propriétés de SAX 2. Ces propriétés indiquent comment certains composants d'un document XML doivent être traités lors du processus de normalisation. Par exemple, les commentaires doivent ils être ignorés, les sections CDATA doivent elles être transformées en noeuds textes, lesquels s'ils sont adjacents doivent ils être fusionnés, les références d'entités doivent elles être développées, etc.
DOMConfiguration config = document.getDomConfig(); DOMStringList liste = config.getParameterNames(); for(int i = 0; i < liste.getLength(); i++){ String nom = liste.item(i); Object valeur = liste.getParameter(nom); System.out.println(nom + " = " + valeur); }
Le premier noeud est obtenu par la méthode getDocumentElement() de l'objet Document.
Element racine = doument.getDocumentElement();
L'élément racine étant un descendant (héritage) d'un noeud, les méthodes et attributs de l'objet Node sont utilisables pour récupérer des informations sur le noeud et sa descendance.
String nom = racine.getNodeName(); String valeur = racine.getNodeValue(); short type = $racine->getNodeType(); Node pere = racine.getParentNode(); NodeList liste_enfants = racine.getChildNodes(); NodeNamedMap attributs = racine.getAttributes(); Document document = racine.getOwnerDocument(); String texte = racine.getTextContent();
D'autres méthodes d'un Node permettent d'accéder aux noeuds environnants.
Node noeud = liste_enfants.item(3); Node premier_enfant = noeud.getFirstChild(); Node dernier_enfant = noeud.getLastChild(); Node grand_frere = noeud.getPreviousSibling(); Node petit_frere = noeud.getNextSibling();
La méthode getChildNodes() est particulièrement utile pour parcourir rapidement et facilement une arborescence XML. Il suffit d'employer une boucle pour accéder à chaque enfant de la liste de noeuds obtenus.
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import java.io.IOException; public class Parcours { public static void main(String[] args) { try { DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); DocumentBuilder analyseur = fabrique.newDocumentBuilder(); Document document = analyseur.parse("employes.xml"); Element racine = document.getDocumentElement(); System.out.println("ELEMENT RACINE"); afficherInfos(racine); NodeList liste = racine.getChildNodes(); System.out.println("ENFANTS DE L'ELEMENT RACINE"); for (int i = 0; i < liste.getLength(); i++) { Node noeud = liste.item(i); afficherInfos(noeud); } } catch (IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } } public static void afficherInfos(Node noeud) { String nom = noeud.getNodeName(); String valeur = noeud.getNodeValue(); short type = noeud.getNodeType(); if (type == Node.ELEMENT_NODE) valeur = noeud.getTextContent(); System.out.println(nom + " (" + type + ") = '" + valeur + "'"); } }
La nouvelle boucle for du JDK 1.5, pourrait également servir à parcourir la liste de noeuds.
for(Node noeud : liste){ afficherInfos(noeud); }
Le parcours complet de l'arborescence demande une fonction récursive afin que chaque élément rencontré puisse être exploré à son tour, s'il possède des noeuds enfants (hasChildNodes()).
Sommaireimport javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import java.io.IOException; public class Parcours { public static void main(String[] args) { try { DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); DocumentBuilder analyseur = fabrique.newDocumentBuilder(); Document document = analyseur.parse("employes.xml"); afficherInfos(document, 0); } catch (IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } } public static void afficherInfos(Node noeud, int niv) { short type = noeud.getNodeType(); String nom = noeud.getNodeName(); String valeur = noeud.getNodeValue(); indenter(niv, type == Node.TEXT_NODE); System.out.print(nom + " (" + type + ") = '"); if(valeur != null && !valeur.matches("^\\s+$")) System.out.print(valeur); System.out.println("'"); if ((type == Node.DOCUMENT_NODE || type == Node.ELEMENT_NODE) && noeud.hasChildNodes()) { NodeList liste = noeud.getChildNodes(); for(int i = 0; i < liste.getLength(); i++) afficherInfos(liste.item(i), niv + 1); } } public static void indenter(int n, boolean texte){ String tab = "\t"; for(int i = 0; i < n; i++){ System.out.print(tab); } if(texte) System.out.print(" - "); else System.out.print(" + "); } }