Consommer un document XML—exemple selon une approche DOM

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);
   }

   private class Affichage extends JFrame {
      Document m_Document;
      public Affichage (Document doc) {
         super ("Affichage d'un document XML avec DOM");
         m_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(m_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. Donne aussi accès aux enfants et aux indices
   //
   public class AdaptateurNoeudDOM {
      private org.w3c.dom.Node m_NoeudDOM;
      public AdaptateurNoeudDOM (org.w3c.dom.Node NoeudDOM) {
         m_NoeudDOM = NoeudDOM;
      }
      //
      // Méthode pour convertir un AdaptateurNoeudDOM en String
      //
      public String toString() {
         String Résultat = NOMS_TYPES_NOEUDS[m_NoeudDOM.getNodeType()];
         String nom = m_NoeudDOM.getNodeName();
         if (nom.length () != 0 && !nom.startsWith("#")) {
            Résultat += ": " + nom;
         }
         if (m_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 = m_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.m_NoeudDOM == anDOM.m_NoeudDOM) {
               return i;
            }
         }
         return -1; // Ne devrait pas se rendre ici.
      }
      public int compterEnfants() {
          return m_NoeudDOM.getChildNodes().getLength();
      }
      public AdaptateurNoeudDOM getEnfant (int ndx) {
         org.w3c.dom.Node noeudDOM =
              m_NoeudDOM.getChildNodes().item(ndx);
         return new AdaptateurNoeudDOM(noeudDOM);
      }
   }

   //
   // Adapte un document pour en faire un modèle de JTree
   // (en gros, du «boilerplate code»)
   //
   public class AdaptateurDOMTreeModel
      implements javax.swing.tree.TreeModel
   {
      private Vector <TreeModelListener> m_ListeObservateurs;
      private Document m_Document;
      public AdaptateurDOMTreeModel (Document doc) {
         m_ListeObservateurs= new Vector<TreeModelListener>();
         m_Document = doc;
      }
      //
      // Opérations de base d'un TreeModel
      //
      public Object getRoot() {
         return new AdaptateurNoeudDOM(m_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 && ! m_ListeObservateurs.contains( observateur ) ) {
            m_ListeObservateurs.addElement( observateur );
         }
      }
      public void removeTreeModelListener(TreeModelListener observateur) {
         if ( observateur != null ) {
            m_ListeObservateurs.removeElement( observateur );
         }
      }

      //
      // ...
      //
      public void fireTreeNodesChanged( TreeModelEvent e ) {
         Enumeration observateurs = m_ListeObservateurs.elements();
         while ( observateurs.hasMoreElements() ) {
            TreeModelListener observateur =
               (TreeModelListener) observateurs.nextElement();
            observateur.treeNodesChanged( e );
         }
      }
      public void fireTreeNodesInserted( TreeModelEvent e ) {
        Enumeration observateurs = m_ListeObservateurs.elements();
        while ( observateurs.hasMoreElements() ) {
           TreeModelListener observateur =
              (TreeModelListener) observateurs.nextElement();
           observateur.treeNodesInserted( e );
        }
      }
      public void fireTreeNodesRemoved( TreeModelEvent e ) {
        Enumeration observateurs = m_ListeObservateurs.elements();
        while ( observateurs.hasMoreElements() ) {
          TreeModelListener observateur =
             (TreeModelListener) observateurs.nextElement();
          observateur.treeNodesRemoved( e );
        }
      }
      public void fireTreeStructureChanged( TreeModelEvent e ) {
        Enumeration observateurs = m_ListeObservateurs.elements();
        while ( observateurs.hasMoreElements() ) {
          TreeModelListener observateur =
             (TreeModelListener) observateurs.nextElement();
          observateur.treeStructureChanged( e );
        }
      }
   }
}

Le code proposé à droite consomme un document XML selon une stratégie DOM et en fait une représentation arborescente à l'écran.

Si vous examinez attentivement le tout, vous remarquerez que le code consommant le document y est plus petit que le code relié à l'affichage—consommer un document XML n'est pas une tâche très douloureuse, surtout en comparaison avec une tâche pleine de petits détails comme celle de gérer une interface personne/ machine.

Notez que j'utilise ici un dérivé de la classe ConsommateurDOM, à laquelle vous pouvez vous référer pour plus de détails.