TP 9, 25/11/2009

DOM

Par Benoît Valiron <benoit.valiron [at] monoidal.net>
Jean Baptiste Faddoul <jean-baptiste.faddoul [at] xrce.xerox.com>

Ce TP reprend en grande partie le TD 9. Les documents du TD sont Document 1 et Document 2. Le TD est accessible en PDF.

  1. Dans un répertoire dédié, créez un fichier Simple.java, contenant le texte suivant :

    import java.io.*;
    import org.w3c.dom.*;
    import org.xml.sax.SAXException;
    import javax.xml.parsers.*;
    
    public class Simple {
        
        public static void main(String[] args) 
            throws SAXException, IOException, ParserConfigurationException {
    
            File file = new File("Document 2.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    	      Document doc = dBuilder.parse(file);
            
            System.out.println(XXX);
        }
    }

    Placez dans le même répertoire le fichier Document 2.xml.

    Répondez aux questions de l'exercice 2 : Pour chacune d'entre elle, modifier la fonction main pour qu'elle affiche le résultat voulu. Dans la question 2, afficher le nom de l'acteur. Dans la question 7, affichez le titre de ces films.

    À chaque fois, compilez et lancez le code avec les commandes :

    javac Simple.java
    java Simple

    Note : Si vous êtes sous windows, vous pouvez utiliser eclipse.

    CORRECTION.

    import java.io.*;
    import org.w3c.dom.*;
    import org.xml.sax.SAXException;
    import javax.xml.parsers.*;
    
    public class Simple2 {
        
        public static void main(String[] args) 
            throws SAXException, IOException, ParserConfigurationException {
    
            File file = new File("Document 2.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(file);
    
            // 1
            
            System.out.println(doc.getElementsByTagName("film").getLength());
    
            // 2
    
            System.out.println( ((Element)((Element) doc.getElementsByTagName("film").item(1)).getElementsByTagName("casting").item(0)).getElementsByTagName("acteur").item(2).getTextContent());
    
            // 3
    	
            for (int i=0;i < doc.getElementsByTagName("film").getLength();i++) {
               Element film = (Element) doc.getElementsByTagName("film").item(i);
               if ( film.hasAttribute("lang") 
                    && film.getAttribute("lang").equals("fr") )
                  System.out.println(film.getElementsByTagName("titre").item(0).getTextContent());
            }
    
            // 4
    
            for (int i=0; i < doc.getElementsByTagName("acteur").getLength(); i++) {
               Element acteur  = (Element) doc.getElementsByTagName("acteur").item(i);
               if ( acteur.hasAttribute("id")
                    && acteur.hasAttribute("personnage")
                    && acteur.getAttribute("id").equals("lukemonfils") )
                  System.out.println(acteur.getAttribute("personnage"));
            }
    
            // 5
    
            for (int i=0;i < doc.getElementsByTagName("film").getLength();i++) {
              Element film = (Element) doc.getElementsByTagName("film").item(i);
              if ( film.getElementsByTagName("annee") !=null 
                   && film.getElementsByTagName("annee").item(0).getTextContent().equals("1981"))
                 System.out.println(film.getElementsByTagName("titre").item(0).getTextContent());
            }
    
            // 6
    
            int num = 0;
            for (int i=0;i < doc.getElementsByTagName("perso").getLength();i++) {
               Element perso = (Element) doc.getElementsByTagName("perso").item(i);
               if ( perso.hasAttribute("ref")
                     && perso.getAttribute("ref").equals("indy"))
                  num++;
            }
            System.out.println(  "le nombre de références faites au personnage " 
                               + "dont l'identifiant est indy : "
                               + num);
    	
            // 7
    
            for (int i=0;i < doc.getElementsByTagName("film").getLength();i++) {
               Element film = (Element) doc.getElementsByTagName("film").item(i);
               if (!film.getElementsByTagName("casting").item(0).hasChildNodes())
                  System.out.println(film.getElementsByTagName("titre").item(0).getTextContent());
            }
        }
  2. Ici, on traite l'exercice 3 du TD

    Pour ce faire, vous allez utiliser le fichier XMLOutput.java, à placer dans le répertoire de travail.

    Ce code propose deux fonctions dump et writeToFile pour respectivement imprimer un noeud Document sur la sortie standard et pour l'imprimer dans un fichier.

    Remplacez le code du fichier Simple.java par :

    import java.io.*;
    import org.w3c.dom.*;
    import org.xml.sax.SAXException;
    import javax.xml.parsers.*;
    
    public class Simple {
        
        public static void main(String[] args) 
            throws SAXException, IOException, ParserConfigurationException {
    
            File file = new File("Document 2.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(file);
            
            // On trouve l'élément <films> du document
            Element racine = (Element) doc.getChildNodes().item(0);
    
            // On crée un élément acteur
            Element a = doc.createElement("acteur");
            
            // que l'on ajoute comme fils de <films>
            racine.appendChild(a);
            
            // finalement, on affiche le résultat.
            XMLOutput.dump(doc);
        }
    }

    Notez : Si vous voulez plutôt placer le résultat dans un fichier, vous pouvez remplacer la ligne

    XMLOutput.dump(doc);

    par

    XMLOutput.writeToFile(doc,"nom_de_fichier.xml");

    Maintenant, compilez les deux fichiers .java et lancez le programme Simple

    javac Simple.java
    javac XMLOutput.java
    java Simple

    Vous devriez voir sur la sortie standard le fichier Document 2.xml, plus un élément film vide à la fin.

    Modifiez le code Simple.java pour répondre à l'exercice 3 du TD.

    CORRECTION.

    import java.io.*;
    import org.w3c.dom.*;
    import org.xml.sax.SAXException;
    import javax.xml.parsers.*;
    
    public class Simple3 {
        
        public static void main(String[] args) 
            throws SAXException, IOException, ParserConfigurationException {
            
            File file = new File("Document 2.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(file);
            
            // On trouve l'élément <films> du document
            Element racine = (Element) doc.getChildNodes().item(0);
    
            // On crée un élément acteur
            Element a = doc.createElement("acteur");
            a.setAttribute("ref","owen");
            a.setAttribute("personnage","Uncle Owen");
            a.setTextContent("Phil Brown");
            
            
            
            Element casting = ((Element)((Element) doc.getElementsByTagName("film").item(1)).getElementsByTagName("casting").item(0));
    
            // que l'on ajoute comme fils de <films>
            casting.appendChild(a);
            
            Element toDell = null;
            for (int i=0;i<doc.getElementsByTagName("film").getLength();i++) {
                Element film = (Element) doc.getElementsByTagName("film").item(i);
                
                if (film.getElementsByTagName("titre").item(0).getTextContent().equals("La Guerre des étoiles")) {
                    film.getElementsByTagName("titre").item(0).setTextContent("star wars");
                    
                    casting = (Element) film.getElementsByTagName("casting").item(0);
                    for (int j = 0 ; j< casting.getElementsByTagName("acteur").getLength(); j++){
                        if (casting.getElementsByTagName("acteur").item(j).getTextContent().equals("Harrison Ford")){
                            casting.removeChild(casting.getElementsByTagName("acteur").item(j));
                            break;
                        }
                    }
                }
            }
            
            Element f  = doc.createElement("film");
            
            Element r  = doc.createElement("realisateur");
            r.setTextContent("Adam Ellio");
            
            Element t  = doc.createElement("titre");
            t.setTextContent("Marie et Max");
            
            Element s = doc.createElement("annee");
            s.setTextContent("2009");
            
            f.appendChild(t);
            f.appendChild(r);        
            f.appendChild(s);
            
            racine.appendChild(f);
            
            
            // finalement, on affiche le résultat.
            XMLOutput.dump(doc);
            
        }
    }
  3. Dans cette question, on va travailler avec le fichier bd.xml et un fichier Template.java qui va contenir le code :

    import java.io.*;
    import org.w3c.dom.*;
    import org.xml.sax.*;
    import com.sun.org.apache.xerces.internal.parsers.DOMParser;
    
    public class Template {
    
    	public static void main(String[] args) throws SAXException, IOException {
    		DOMParser parser = new DOMParser();
    		parser.parse("bd.xml");
    		Document doc = parser.getDocument();
    		
    		System.out.println("Number 1");
    		System.out.println(doc.getChildNodes().item(0).hasAttributes());
    		
    
    		System.out.println("Number  2");
    		System.out.println(doc.getChildNodes().item(0).getChildNodes().item(1).getTextContent());
    
    	
    		System.out.println("Number  3");
    		System.out.println(doc.getChildNodes().item(0).getChildNodes().item(0).hasChildNodes());
    		
    		
    		System.out.println("Number 4");
    		System.out.println(((Element) doc.getElementsByTagName("serie").item(0)).getTextContent());
    
    
    	}
    
    }
    1. Tout d'abord :

      1. Placez les fichiers Template.java et bd.xml dans le répertoire de travail.
      2. Placez vous dans ce repertoire.
      3. Compilez le fichier par la commande : javac Template.java
      4. Executez le par : java Template
      5. Faites l'association entre les expressions dans le fichier et la sortie sur la console.
    2. Reprenez le fichier Template.java. Effacez les expressions DOM (ligne 17 jusqu'au 30).

      Écrivez vos bouts de code pour répondre aux questions suivantes:

      1. Le nombre de séries.
      2. Le nombre de bd dans la série 'Lanfeust de Troy'.
      3. Les personnes qui sont auteur et illustrateur dans la même bd.
      4. Les bds qui sont sans série.
      5. Le titre des bds de l'auteur "Manu".
      6. Est ce que les bds "Les projets"et "L'enquête corse" appartiennent au même série?
      import java.io.*;
      import org.w3c.dom.*;
      import org.xml.sax.*;
      import com.sun.org.apache.xerces.internal.parsers.DOMParser;
      
      public class Template {
          
          public static void main(String[] args) throws SAXException, IOException {
              DOMParser parser = new DOMParser();
              parser.parse("bd.xml");
              Document doc = parser.getDocument();
              
              // a
              System.out.println(doc.getElementsByTagName("serie").getLength());
              
              // b
              System.out.println(((Element) doc.getElementsByTagName("serie").item(0)).getElementsByTagName("bd").getLength());
              
              // c
              NodeList per = doc.getElementsByTagName("personne");
              NodeList bds = doc.getElementsByTagName("bd");
              for(int i = 0 ; i < per.getLength(); ++i) {
                  // pour chacune des personnes
                  boolean est_auteur = false;
                  boolean est_illust = false;
                  String id_pers = ((Element) per.item(i)).getAttribute("id");
                  // on cherche dans les bds/
                  for (int j = 0 ; j < bds.getLength(); ++j) {
                      // pour chacune des bds
                      Element bd = (Element) bds.item(j);
                      // on cherche dans les auteurs
                      NodeList auteurs = bd.getElementsByTagName("auteur");
                      for (int k = 0; k < auteurs.getLength(); ++k) {
                          est_auteur = est_auteur || ((Element) auteurs.item(k)).getAttribute("ref").equals(id_pers);
                      }
                      // on cherche dans les illustrateurs
                      NodeList illustrateurs = bd.getElementsByTagName("illustrateur");
                      for (int k = 0; k < auteurs.getLength(); ++k) {
                          est_illust = est_illust || ((Element) illustrateurs.item(k)).getAttribute("ref").equals(id_pers);
                      }
                  }
                  // si les deux sont vrais, on affiche le nom de la personne.
                  if (est_auteur && est_illust) {
                      System.out.println(((Element)per.item(i)).getElementsByTagName("nom").item(0).getTextContent());
                  }                        
              }
              
              // d
              // on réutilise la variable bds
              for(int j = 0 ; j < bds.getLength(); ++j) {
                  if (((Element) bds.item(j).getParentNode()).getLocalName().equals("serie")) {
                      System.out.println(((Element)bds.item(j)).getElementsByTagName("titre").item(0).getTextContent());
                  }
              }
              
              // e
              // on cherche dans la liste bds
              // Note : on cherche les BDs dont Larcenet est l'illustrateur (il n'est l'auteur de rien)
              for(int j = 0 ; j < bds.getLength(); ++j) {
                  Element bd = (Element) bds.item(j);
                  // on cherche dans les auteurs
                  NodeList auteurs = bd.getElementsByTagName("illustrateur");
                  for (int k = 0; k < auteurs.getLength(); ++k) {
                      String ref_auteur = ((Element) auteurs.item(k)).getAttribute("ref");
                      if (ref_auteur.equals("Larcenet")) {
                          System.out.println(((Element)bds.item(j)).getElementsByTagName("titre").item(0).getTextContent());
                      }
                  }
              }
              
              // f
              //On cherche la serie de L'enquete corse:
              Element serie = null;
              for(int j = 0 ; j < bds.getLength(); ++j) {
                  Element bd = (Element) bds.item(j);
                  if (((Element) bd.getElementsByTagName("titre").item(0)).getTextContent().equals("L'enquête corse")) {
                      serie = (Element) bd.getParentNode();
                      break;
                  }
              }
              // Maintenant, on regarde si dans la serie on a "Les Projets" comme titre de BD:
              NodeList s_liste = serie.getElementsByTagName("titre");
              boolean la_meme = false;
              for(int j = 0 ; j < s_liste.getLength(); ++j) {
                  if (((Element) s_liste.item(j)).getTextContent().equals("Les Projets")) {
                      la_meme = true;
                      break;
                  }
              }
              if (la_meme) System.out.println("Oui");
              else System.out.println("Non");
          }
      }
    3. De nouveau, reprenez le fichier Template.java. Effacez les expressions DOM.

      Écrivez vos bouts de code pour faire les modifications suivantes:

      1. Ajoutez une bd à la série "Le retour à la terre" donnez-lui comme titre "Le vaste monde", auteur "JYFerri", illustrateur "Larcenet", sortie en 2004
      2. Ajouter au résumé de "L'enquête corse" n'importe quelle texte.
      3. Supprimer "Ange Leoni" de "L'enquête corse".
      4. Ajoutez une personne avec le nom "X" et ref "X".
      5. Remplacez l'illustrateur du "L'enquête corse" par la nouvelle personne X.

      Vous pouvez utiliser XMLOutput.dump pour afficher le résultat.

      import java.io.*;
      
      import javax.xml.parsers.ParserConfigurationException;
      
      import org.w3c.dom.*;
      import org.xml.sax.*;
      import com.sun.org.apache.xerces.internal.parsers.DOMParser;
      
      public class CopyOfTemplate {
          
          public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException {
              DOMParser parser = new DOMParser();
              parser.parse("bd.xml");
              Document doc = parser.getDocument();
              
              // a
      	
              NodeList titre_serie = doc.getElementsByTagName("titreserie");
      	
              Element serie_retour = null;
              for (int i = 0; i < titre_serie.getLength(); ++i) {
                  if(titre_serie.item(i).getTextContent().equals("Le retour à la terre")) {
                      serie_retour = (Element) titre_serie.item(i).getParentNode();
                  }
              }
              if (serie_retour != null) {
                  
                  Element nouvelle_bd = doc.createElement("bd");
                  Element nouveau_titre = doc.createElement("titre");
                  Element nouveau_auteur = doc.createElement("auteur");
                  Element nouveau_illustrateur = doc.createElement("illustrateur");
                  Element nouveau_sortie = doc.createElement("sortie");
                  Node titre_texte = doc.createTextNode("Le vaste monde");
                  Node sortie_texte = doc.createTextNode("2004");
                  nouveau_titre.appendChild(titre_texte);
                  nouveau_sortie.appendChild(sortie_texte);
                  nouveau_illustrateur.setAttribute("ref", "Larcenet");
                  nouveau_auteur.setAttribute("ref", "JYFerri");
                  nouvelle_bd.appendChild(nouveau_titre);
                  nouvelle_bd.appendChild(nouveau_sortie);
                  nouvelle_bd.appendChild(nouveau_illustrateur);
                  nouvelle_bd.appendChild(nouveau_auteur);
                  
                  serie_retour.appendChild(nouvelle_bd);
              } else {
                  System.out.println("erreur a...");
              }
      	
              // b, c, d
      	
              NodeList bds = doc.getElementsByTagName("titre");
              Element bd_enquete = null;
              for (int i = 0; i < bds.getLength(); ++i) {
                  if(bds.item(i).getTextContent().equals("L'enquête corse")) {
                      bd_enquete = (Element) bds.item(i).getParentNode();
                  }
              }
              if (bd_enquete != null) {
                  // b
                  Node random_text = doc.createTextNode("Blah Blah Blah Blah Blah");
                  bd_enquete.getElementsByTagName("resume").item(0).appendChild(random_text);
                  // c
                  bd_enquete.getElementsByTagName("resume").item(0).removeChild(bd_enquete.getElementsByTagName("perso").item(1));
                  // d
                  Element p = doc.createElement("personne");
                  p.setAttribute("id", "X");
                  Element n = doc.createElement("nom");
                  n.appendChild(doc.createTextNode("X"));
                  p.appendChild(n);
                  doc.getElementsByTagName("personnes").item(0).appendChild(p);
                  // e
                  ((Element)bd_enquete.getElementsByTagName("illustrateur").item(0)).setAttribute("ref","X");
              } else {
                  System.out.println("erreur bcde...");
              }
      	
              XMLOutput.dump(doc);
          }    
      }