Exemple de consommation d'un document XML avec Java, manière DOM

Voici un exemple opérationnel de code Java capable de consommer un document XML selon une stratégie DOM.

La classe ConsommateurDOM proposée à droite se veut une classe parent pour diverses classes Java capables de consommer des documents selon une approche DOM.

Si vous désirez utiliser cette technique, les classes dérivant de ConsommateurDOM devront implémenter la méthode abstraite traiter() pour consommer le document XML à proprement dit. Un exemple complet de consommation d'un document XML, affichant graphiquement la structure de ce document dans un arbre, est proposé plus bas.

Étant un peu lâche, je me suis fortement inspiré du code sur cette page, qui est correct sans être renversant.

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import java.io.File;
import java.io.IOException;

import org.w3c.dom.Document;
import org.w3c.dom.DOMException;

public abstract class ConsommateurDOM {
   public ConsommateurDOM () {
   }
   protected abstract void traiter (Document doc);
   public void consommer (String nomFich) {
      DocumentBuilderFactory Fabrique =
         DocumentBuilderFactory.newInstance();
      // Fabrique.setValidating(true);
      Fabrique.setNamespaceAware(true);
      try {
         DocumentBuilder bâtisseur =
            Fabrique.newDocumentBuilder();
         Document doc =
            bâtisseur.parse (new File(nomFich));
         traiter (doc);
      } catch (SAXException sxe) {
         Exception ex =
            (sxe.getException() != null)?
               sxe.getException() : sxe;
         ex.printStackTrace();
      } catch (ParserConfigurationException pce) {
         pce.printStackTrace();
      } catch (IOException ioe) {
         ioe.printStackTrace();
      }
   }
}
import org.w3c.dom.Document;
//
// éléments pour l'interface personne/ machine
//
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.JSplitPane;
import javax.swing.JEditorPane;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
//
// éléments pour l'arbre et son modèle
//
import javax.swing.tree.*;
import javax.swing.event.*;
import java.util.*;
//
// Notre petite classe
//
public class AfficheurDOM extends ConsommateurDOM {
   public static void main (String [] args) {
      if (args.length == 0) {
         System.err.println ("Usage: java AfficheurDOM fichierXML [fichierXML ...]");
      } else {
         for (String s : args) {
            AfficheurDOM ad = new AfficheurDOM ();
            ad.consommer (s);
         }
      }
   }
   //
   // Le traitement du document à proprement dit
   //
   protected void traiter (Document doc) {
      Affichage aff = new Affichage (doc);
      aff.init ();
      aff.addWindowListener (
         new WindowAdapter () {
            public void windowClosing (WindowEvent we) {
               System.exit (0);
            }
         }
      );
      aff.pack();
      aff.setVisible (true);
   }
   //
   // Classe présentant un Document dans un JTree
   //
   private class Affichage extends JFrame {
      Document document_;
      public Affichage (Document doc) {
         super ("Affichage d'un document XML avec DOM");
         document_ = doc;
      }
      public void init () {
         final int HAUTEUR = 460;
         final int LARGEUR_GAUCHE = 300;
         final int LARGEUR_DROITE = 340;
         final int LARGEUR_TOTALE = LARGEUR_GAUCHE + LARGEUR_DROITE;
         final int éPAISSEUR_BORDURE = 5;
         final int ESPACEMENT = éPAISSEUR_BORDURE * 2;
         //
         // Nous allons afficher le document dans un arbre
         // (c'est assez naturel comme représentation)
         //
         JTree arborescence = new JTree(new AdaptateurDOMTreeModel(document_));
         //
         // Côté gauche...
         //
         JScrollPane vueEnArbre = new JScrollPane(arborescence);
         vueEnArbre.setPreferredSize
            (new Dimension (LARGEUR_GAUCHE, LARGEUR_TOTALE));
         //
         // Côté droit...
         //
         JEditorPane panneauHTML = new JEditorPane("text/html","");
         panneauHTML.setEditable(false);
         JScrollPane vueHTML = new JScrollPane(panneauHTML);
         vueHTML.setPreferredSize
            (new Dimension(LARGEUR_DROITE, LARGEUR_TOTALE));
         //
         // Vue séparée en deux...
         //
         JSplitPane panneauSéparé =
            new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, vueEnArbre, vueHTML);
         panneauSéparé.setContinuousLayout( true );
         panneauSéparé.setDividerLocation( LARGEUR_GAUCHE );
         panneauSéparé.setPreferredSize
            (new Dimension(LARGEUR_TOTALE + ESPACEMENT, LARGEUR_TOTALE + ESPACEMENT));
         setLayout(new BorderLayout());
         add(panneauSéparé, BorderLayout.CENTER);
      }
   }

   //
   // Tableau contenant les noms des types de noeuds DOM. Les indices
   // correspondent aux valeurs des types dans org.w3c.dom.Node, plus bas
   //
   private static final String[] NOMS_TYPES_NOEUDS = {
      "none",
      "Element",
      "Attr",
      "Text",
      "CDATA",
      "EntityRef",
      "Entity",
      "ProcInstr",
      "Comment",
      "Document",
      "DocType",
      "DocFragment",
      "Notation"
   };

   //
   // Enrobe un noeud DOM en donnant accès au texte à afficher dans l'arbre.
   //
   public class AdaptateurNoeudDOM {
      private org.w3c.dom.Node noeudDOM_;
      public AdaptateurNoeudDOM (org.w3c.dom.Node noeudDOM) {
        noeudDOM_ = noeudDOM;
      }
      //
      // Méthode pour convertir un AdaptateurNoeudDOM en String
      //
      public String toString() {
         String résultat = NOMS_TYPES_NOEUDS[noeudDOM_.getNodeType()];
         String nom = noeudDOM_.getNodeName();
         if (nom.length () != 0 && !nom.startsWith("#")) {
            résultat += ": " + nom;
         }
         if (noeudDOM_.getNodeValue() != null) {
            if (résultat.startsWith("ProcInstr")) {
               résultat += ", ";
            } else {
               résultat += ": ";
            }
            //
            // Nettoyage au cas où le texte commencerait par des blancs ou un saut de ligne
            //
            String s = noeudDOM_.getNodeValue().trim();
            int ndxNouvelleLigne = s.indexOf("\n");
            if (ndxNouvelleLigne >= 0) {
               s = s.substring(0, ndxNouvelleLigne);
            }
            if (s.length () > 0) {
               résultat += s;
            } else {
               résultat = "(vide)";
            }
         }
         return résultat;
      }
      //
      // Cherche l'index d'un enfant
      //
      public int index(AdaptateurNoeudDOM Enfant) {
         int NombreEnfants = compterEnfants();
         for (int i = 0; i < NombreEnfants; i++) {
            AdaptateurNoeudDOM anDOM = getEnfant(i);
            if (Enfant.noeudDOM_ == anDOM.noeudDOM_) {
               return i;
            }
         }
         return -1; // hum...
      }
      public int compterEnfants() {
          return noeudDOM_.getChildNodes().getLength();
      }
      public AdaptateurNoeudDOM getEnfant (int ndx) {
         org.w3c.dom.Node noeudDOM =
             noeudDOM_.getChildNodes().item(ndx);
         return new AdaptateurNoeudDOM(noeudDOM);
      }
   }

   //
   // Adapte un document pour en faire un modèle de Jtree (du «boilerplate code»)
   //
   public class AdaptateurDOMTreeModel implements javax.swing.tree.TreeModel {
      private Vector <TreeModelListener> observateurs_;
      private Document document_;
      public AdaptateurDOMTreeModel (Document doc) {
         observateurs_ = new Vector<TreeModelListener>();
         document_ = doc;
      }
      //
      // Opérations de base d'un TreeModel
      //
      public Object getRoot() {
         return new AdaptateurNoeudDOM(document_);
      }
      public boolean isLeaf(Object aNode) {
         AdaptateurNoeudDOM node = (AdaptateurNoeudDOM) aNode;
         return node.compterEnfants() <= 0;
      }
      public int getChildCount(Object parent) {
         AdaptateurNoeudDOM noeud = (AdaptateurNoeudDOM) parent;
         return noeud.compterEnfants();
      }
      public Object getChild(Object parent, int index) {
         AdaptateurNoeudDOM noeud = (AdaptateurNoeudDOM) parent;
         return noeud.getEnfant(index);
      }
      public int getIndexOfChild(Object parent, Object enfant) {
         AdaptateurNoeudDOM noeud = (AdaptateurNoeudDOM) parent;
         return noeud.index((AdaptateurNoeudDOM) enfant);
      }
      public void valueForPathChanged(TreePath path, Object newValue) {
         // sans intérêt pour nous
      }
      //
      // On doit implémenter celles-ci mais on ne s'en servira pas
      //
      public void addTreeModelListener(TreeModelListener observateur) {
         if ( observateur != null && ! observateurs_.contains( observateur ) ) {
            observateurs_.addElement( observateur );
         }
      }
      public void removeTreeModelListener(TreeModelListener observateur) {
         if ( observateur != null ) {
            observateurs_.removeElement( observateur );
         }
      }
      public void fireTreeNodesChanged( TreeModelEvent e ) {
         Enumeration observateurs = observateurs_.elements();
         while ( observateurs.hasMoreElements() ) {
            TreeModelListener observateur =
               (TreeModelListener) observateurs.nextElement();
            observateur.treeNodesChanged( e );
         }
      }
      public void fireTreeNodesInserted( TreeModelEvent e ) {
        Enumeration observateurs = observateurs_.elements();
        while ( observateurs.hasMoreElements() ) {
           TreeModelListener observateur =
              (TreeModelListener) observateurs.nextElement();
           observateur.treeNodesInserted( e );
        }
      }
      public void fireTreeNodesRemoved( TreeModelEvent e ) {
        Enumeration observateurs = observateurs_.elements();
        while ( observateurs.hasMoreElements() ) {
          TreeModelListener observateur =
             (TreeModelListener) observateurs.nextElement();
          observateur.treeNodesRemoved( e );
        }
      }
      public void fireTreeStructureChanged( TreeModelEvent e ) {
        Enumeration observateurs = observateurs_.elements();
        while ( observateurs.hasMoreElements() ) {
          TreeModelListener observateur =
             (TreeModelListener) observateurs.nextElement();
          observateur.treeStructureChanged( e );
        }
      }
   }
}

Valid XHTML 1.0 Transitional

CSS Valide !