Sax "Parseur" XML

1. Simple Parsing d'un document XML (non validant)

Programme

// Analyse0.java

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
// et une tartine de classe !

public class Analyse0 extends DefaultHandler {
  public static void main (String argv[])
  throws IOException {
    if (argv.length != 1) {
      System.err.println 
        ("Usage: Analyse0 fichierSource");
      System.exit (1);
    }
    DefaultHandler handler = new DefaultHandler();
    // le handler réalise les traitements 
    // pendant le parsing
    // içi : celui par defaut qui ne fait rien
    SAXParserFactory factory = 
                   SAXParserFactory.newInstance();
    // une "factory" (configurateur) de parseur
    // içi : celui par defaut
    try {
      SAXParser saxParser = factory.newSAXParser();
      // obtenir un parseur ("compilateur") XML
      saxParser.parse( new File(argv[0]), handler );
      // parser (compiler) le fichier en réalisant
      // les traiements indiqués
    } catch (Throwable t) {
      t.printStackTrace ();
    }
    System.exit (0);
  }
}

commandes et résultats

$ javac -classpath .:/usr/local/jaxp-1.1/jaxp.jar:
/usr/local/jaxp-1.1/crimson.jar:
/usr/local/jaxp-1.1/xalan.jar Analyse0.java 
indiquer le chemin d'accès aux packages "XML" de sun (la version JAXP 1.1)
$ java -classpath .:/usr/local/jaxp-1.1/jaxp.jar:
/usr/local/jaxp-1.1/crimson.jar:
/usr/local/jaxp-1.1/xalan.jar Analyse0 dialogue2.xml  
$

un document mal formé

fichier dialogue1err1.xml :
 

<?xml version='1.0' encoding='ISO-8859-1'  ?>
<!-- fichier dialogue1err1.xml -->
<dialogue>
<situation>acte I, Scene 1 : madame pernelle et flipote sa servante,elmire, mariane, dorine, damis, cléante.</situation>
<!-- erreur -->
</replique>
<personnage>madame pernelle</personnage>
<texte>Allons, Flipote, allons, que d'eux je ......

parsing :

$ CLASSPATH=.:/usr/local/jaxp-1.1/jaxp.jar:
/usr/local/jaxp-1.1/crimson.jar:
/usr/local/jaxp-1.1/xalan.jar
évite l'option pénible et répétitive -classpath

$ java Analyse0 dialogue1err1.xml
org.xml.sax.SAXParseException: org.apache.crimson.parser/P-034 dialogue 5
at org.apache.crimson.parser.Parser2.fatal(Parser2.java:3035)
at org.apache.crimson.parser.Parser2.fatal(Parser2.java:3029)
at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java, Compiled Code)
at org.apache.crimson.parser.Parser2.parseInternal(Parser2.java:499)
at org.apache.crimson.parser.Parser2.parse(Parser2.java:304)
at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:433)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:346)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:286)
at Analyse0.main(Analyse0.java:25)

 

 

2. "Parsing" validant

Programme

// Analyse1.java

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;

public class Analyse1 extends DefaultHandler {
  public static void main (String argv[])
  throws IOException {
    if (argv.length != 1) {
      System.err.println 
        ("Usage: Analyse1 fichierSource");
      System.exit (2);
    }
    DefaultHandler handler = new Analyse1();
    SAXParserFactory factory = SAXParserFactory.newInstance();
    factory.setValidating(true);
    // la factory produira un parseur validant 
    try {
      SAXParser saxParser = factory.newSAXParser();
      saxParser.parse( new File(argv[0]), handler );
    } catch (SAXException e) {
    // prise en charge des erreurs SAX 
    // donc en particulier celles de parsing
      System.out.println ("erreur de parsing");
      System.exit (1);
    } catch (Throwable t) {
      t.printStackTrace ();
      System.out.println ("erreur autre que parsing");
    System.exit (2);
    }
    System.out.println ("parsing reussi");
    System.exit (0);
  }
  public void error(SAXParseException e)
  // le "handler" (le traitement) lors du
  // parsing d'une erreur
  throws SAXParseException
  {
    throw e;
    // transmettre au lieu, par defaut, d'ignorer
  }
}

 

commandes et résultats

$  java Analyse1 dialogue3.xml
parsing reussi
 

un document non valide

fichier dialogue3err1.xml :

<?xml version='1.0' encoding='ISO-8859-1' standalone='no' ?>
<!-- fichier dialogue3err1.xml -->

<!DOCTYPE dialogue SYSTEM "dia2.dtd">

<!-- extrait de Tartuffe de Molière -->
<dialogue>
<situation>acte I, Scene 1 : madame pernelle et flipote sa servante,elmire, mariane, dorine, damis, cléante.</situation>
<replique>
<texte>Allons, Flipote, allons, que d'eux je me délivre.</texte>
<personnage>madame pernelle</personnage>
</replique>
</dialogue>

parsing validant :

$  java Analyse1 dialogue3err1.xml
erreur de parsing
$  java Analyse0 dialogue3err1.xml
Analyse0 n'est pas un parseur validant et
dialogue3err1.xml est bien formé !
 

traitement des erreurs :

// Analyse2.java

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
public class Analyse2 extends DefaultHandler {
  public static void main (String argv[])
  throws IOException {
    if (argv.length != 1) {
      System.err.println 
        ("Usage: Analyse2 fichierSource");
      System.exit (1);
    }
    DefaultHandler handler = new Analyse2();
    SAXParserFactory factory = SAXParserFactory.newInstance();
    factory.setValidating(true);
    try {
      SAXParser saxParser = factory.newSAXParser();
      saxParser.parse( new File(argv[0]), handler );
    } catch (SAXParseException e) {
      // prise en charge des erreurs de parsing
      System.out.println("\n** Parsing error"
              + ", line " + e.getLineNumber()
              + ", uri " + e.getSystemId());
      System.out.println("   " + e.getMessage() );
      if (e.getException() != null)
         e.getException().printStackTrace();
      System.exit (2);
    } catch (SAXException e) {
     // prise des erreurs SAX
     if (e.getException() != null)
         e.getException().printStackTrace();
      System.exit (3);
    } catch (ParserConfigurationException e) {
    // prise en charge des erreurs de 
    // configuration (factory)
      e.printStackTrace();
      System.exit (4);
    } catch (IOException e) {
      e.printStackTrace();
      System.exit (5);
    }
    System.out.println ("parsing reussi");
    System.exit (0);
  }
  public void error(SAXParseException e)
  throws SAXParseException
  {
    throw e;
  }
}

$  java Analyse2 dialogue3err1.xml
** Parsing error, line 10, 
   uri file:/home/ferment/site_upjv/xml/dialogue3err1.xml
   org.apache.crimson.parser/V-036 replique texte
$  java Analyse2 dialogue1err1.xml
** Parsing error, line 5, 
   uri file:/home/ferment/site_upjv/xml/dialogue1err1.xml   org.apache.crimson.parser/V-005 dialogue

3. "Parsing" ET traitement par Handler

Programme

// Analyse3.java

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;

public class Analyse3 extends DefaultHandler {
// plusieures méthodes de DefaultHandler (qui
// ne font rien) vont être redéfinies
  static private FileWriter dest;
  public static void main (String argv[])
  throws IOException {
    if (argv.length != 2) {
      System.err.println
         ("Usage: Analyse3 fichierSource fichierCible");
      System.exit (1);
    }
    File fichierDest = new File(argv[1]);
    dest = new FileWriter(fichierDest);
    DefaultHandler handler = new Analyse3();
    // les "handlers" (traitement) seront ceux de
    // la classe Analyse3 
    SAXParserFactory factory = SAXParserFactory.newInstance();
    try {
      SAXParser saxParser = factory.newSAXParser();
      saxParser.parse( new File(argv[0]), handler );
    // parser et lancer les traitements du handler 
    } catch (Throwable t) {
      t.printStackTrace ();
      System.exit (2);
    }
    System.exit (0);
  }
  public void error(SAXParseException e)
  // le "handler" (traitement) d'une erreur
  throws SAXParseException
  {
    throw e;
  }
  public void startDocument ()
  // le "handler" de la balise debut-racine
  throws SAXException {
    ecrit("startDocument");
    nl();
  }
  public void endDocument ()
  // le "handler" appelé lors du parsing
  // de la balise de fin de document
  throws SAXException {
    ecrit("endDocument");
    nl();
  }
  public void startElement (String namespaceURI,
                             String simpleName,
                             String qualifiedName,
                             Attributes attrs)
  // le "handler" appelé lors du parsing <element>
    throws SAXException {
    ecrit("startElement : "+ simpleName);
    nl();
  }
  public void endElement (String namespaceURI,
                           String simpleName,
                           String qualifiedName)
  // le "handler" appelé lors du parsing </element>
  throws SAXException {
    ecrit("endElement : "+ simpleName);
    nl();
  }
  public void characters (char buf [], 
                        int offset, int len)
  // le "handler" appelé lors du parsing de PCDATA
  throws SAXException {
    String s = new String(buf, offset, len);
    ecrit (s);
    nl();
  }
  private void nl()
  throws SAXException {
    String lineEnd =  System.getProperty("line.separator");
    try {
      dest.write (lineEnd);
    } catch (IOException e) {
      throw new SAXException ("I/O error", e);
    }
  }
  private void ecrit(String s)
  throws SAXException {
    try {
      dest.write (s);
      dest.flush ();
    } catch (IOException e) {
      throw new SAXException ("I/O error", e);
    }
  }
}
  

commandes et résultats

$ java Analyse3 dialogue3.xml result.txt
[ferment@didier xml]$  more result.txt
startDocument
startElement : dialogue
startElement : situation
acte I, Scene 1 : madame pernelle et flipote sa servante, elmire, mariane, dorine, damis, cléante.
endElement : situation
startElement : replique
startElement : personnage
madame pernelle
endElement : personnage
startElement : texte
Allons, Flipote, allons, que d'eux je me délivre.
endElement : texte
endElement : replique
startElement : replique
startElement : personnage
elmire
endElement : personnage
startElement : texte
Vous marchez d'un tel pas qu'on a peine à vous suivre.
endElement : texte
endElement : replique
startElement : replique
startElement : personnage
madame pernelle
endElement : personnage
startElement : texte
Laissez, ma bru, laissez, ne venez pas plus loin: Ce sont toutes façons dont je
n'ai pas besoin.
endElement : texte
endElement : replique
startElement : replique
startElement : personnage
elmire
endElement : personnage
startElement : texte
De ce que l'on vous doit envers vous on s'acquitte, Mais ma mère, d'où vient que vous sortez si vite;
endElement : texte
endElement : replique
  

autre "parsing"

$ javac Analyse3.java
$ java Analyse3 dialogue5.xml result.txt
$ cat result.txt
startDocument
startElement
startElement
acte I, Scene 1 :
madame pernelle
et flipote sa servante,
elmire
, mariane, dorine, damis, cléante.
    les entités internes et externes ont été résolues !
endElement
startElement
startElement
madame pernelle
endElement
startElement
Allons, Flipote, allons, que d'eux je me délivre.
endElement
endElement
startElement
startElement
elmire
endElement
startElement
Vous marchez d'un tel pas qu'on a peine à vous suivre.
endElement
endElement
startElement
startElement
madame pernelle
endElement
startElement
Laissez, ma bru, laissez, ne venez pas plus loin: Ce sont toutes façons dont je n'ai pas besoin.
endElement
endElement
startElement
startElement
elmire
endElement
startElement
De ce que l'on vous doit envers vous on s'acquitte, Mais ma mère, d'où vient que vous sortez si vite;
endElement
endElement
endElement
endDocument

 

4.  Qu'est-ce que SAX ?

 les packages Java

5. Traitement des attributs

Programme

// Analyse4.java

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
public class Analyse4 extends DefaultHandler {
  static private FileWriter dest;
  public static void main (String argv[])
  throws IOException {
    if (argv.length != 2) {
      System.err.println
         ("Usage: Analyse4 fichierSource fichierCible");
      System.exit (1);
    }
    File fichierDest = new File(argv[1]);
    dest = new FileWriter(fichierDest);
    DefaultHandler handler = new Analyse4();
    SAXParserFactory factory = S
              AXParserFactory.newInstance();
    try {
      SAXParser saxParser = factory.newSAXParser();
      saxParser.parse( new File(argv[0]), handler );
    } catch (Throwable t) {
      t.printStackTrace ();
      System.exit (2);
    }
    System.exit (0);
  }
  public void error(SAXParseException e)
  throws SAXParseException
  {
    throw e;
  }
  public void startDocument ()
  throws SAXException {
    ecrit("startDocument");
    nl();
  }
  public void endDocument ()
  throws SAXException {
    ecrit("endDocument");
    nl();
  }
  public void startElement (String namespaceURI,
                             String simpleName,
                             String qualifiedName,
                             Attributes attrs)
    throws SAXException {
    String  elementName = simpleName;
    if (elementName.equals(""))
      elementName = qualifiedName;
    ecrit("startElement : "+ elementName);
    // le nom de l'élément selon que le 
    // namespace est pris ou non en charge
    nl();
    if (attrs != null)
    // recuperation des attributs de l'élément
    // nombre : getLength,  valeur : getValue
    // nom : getLocalName ou getQName selon
    // namespace ou pas
      for (int i = 0; i < attrs.getLength(); i++) {
        ecrit("attributs :"); nl();
        String attName = attrs.getLocalName(i);
        if (attName.equals(""))
          attName = attrs.getQName(i);
        ecrit(attName+"=\""+attrs.getValue(i)+"\"");
        nl();
      }
  }
  public void endElement (String namespaceURI,
                           String simpleName,
                           String qualifiedName)
  throws SAXException {
    String  elementName = simpleName;
    if (elementName.equals(""))
      elementName = qualifiedName;
    ecrit("endElement : "+ elementName);
    nl();
  }
  public void characters (char buf [], int offset, int len)
  throws SAXException {
    String s = new String(buf, offset, len);
    ecrit (s);
    nl();
  }
  private void nl()
  throws SAXException {
    String lineEnd =  System.getProperty("line.separator");
    try {
      dest.write (lineEnd);
    } catch (IOException e) {
      throw new SAXException ("I/O error", e);
    }
  }
  private void ecrit(String s)
  throws SAXException {
    try {
      dest.write (s);
      dest.flush ();
    } catch (IOException e) {
      throw new SAXException ("I/O error", e);
    }
  }
}

commandes et résultats

java Analyse4 dialogue6.xml result.txt
$ cat result.txt
startDocument
startElement : dialogue
startElement : situation
acte I, Scene 1 : madame pernelle et flipote sa servante,elmire, mariane, dorine, damis, cléante.
endElement : situation
startElement : replique
startElement : personnage
attributs :
attitude="pressée"
attributs :
geste="marchant vite"
madame pernelle
endElement : personnage
startElement : texte
attributs :
ton="fort"
Allons, Flipote, allons, que d'eux je me délivre.
endElement : texte
endElement : replique
startElement : replique
startElement : personnage
attributs :
attitude="essouflée"
elmire
endElement : personnage
startElement : texte
attributs :
ton="normal"
Vous marchez d'un tel pas qu'on a peine à vous suivre.
    l'attribut ne figure pas dans le document XML initial, mais il 
     est défini par défaut avec la valeur 'normal' 
endElement : texte
endElement : replique
startElement : replique
startElement : personnage
attributs :
attitude="agacée"
madame pernelle
endElement : personnage
startElement : texte
attributs :
ton="normal"
Laissez, ma bru, laissez, ne venez pas plus loin: Ce sont toutes façons dont je
n'ai pas besoin.
endElement : texte
endElement : replique
startElement : replique
startElement : personnage
attributs :
attitude="étonnée"
elmire
endElement : personnage
startElement : texte
attributs :
ton="normal"
De ce que l'on vous doit envers vous on s'acquitte, Mais ma mère, d'où vient que vous sortez si vite;
endElement : texte
endElement : replique
endElement : dialogue
endDocument

6. Transformation XML --> HTML

Programme

// Analyse5.java

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
public class Analyse5 extends DefaultHandler {
  static private FileWriter dest;
  static private int premiereReplique = 0 ;
  public static void main (String argv[])
  throws IOException {
    if (argv.length != 2) {
      System.err.println
         ("Usage: Analyse5 fichierSource fichierCible");
      System.exit (1);
    }
    File fichierDest = new File(argv[1]);
    dest = new FileWriter(fichierDest);
    DefaultHandler handler = new Analyse5();
    SAXParserFactory factory = SAXParserFactory.newInstance();
    try {
      SAXParser saxParser = factory.newSAXParser();
      saxParser.parse( new File(argv[0]), handler );
    } catch (Throwable t) {
      t.printStackTrace ();
      System.exit (2);
    }
    System.exit (0);
  }
  public void error(SAXParseException e)
  throws SAXParseException
  {
    throw e;
  }

  public void startDocument ()
   throws SAXException {
     ecrit("<!doctype html public \"-//W3C//DTD HTML 3.2 Final//EN\">"); nl();
     ecrit("<html>"); nl();
     ecrit("<head></head>"); nl();
     ecrit("<body>"); nl();
   }
  public void endDocument ()
   throws SAXException {
     ecrit("</dl>"); nl();
     ecrit("</body>"); nl();
     ecrit("</html>"); nl();
     try {
       dest.flush ();
     } catch (IOException e) {
       throw new SAXException ("I/O error", e);
     }
   }
  public void startElement (String namespaceURI,
                             String simpleName,
                             String qualifiedName,
                             Attributes attrs)
    throws SAXException {
    String  name = simpleName;
    if (name.equals(""))
      name = qualifiedName;
    if ( name.equals("situation") ) {
      ecrit("<h5>"+name+"</h5>"); nl();
      ecrit("<p><i>");
    } else if ( name.equals("replique") ) {
      premiereReplique ++;
      if ( premiereReplique == 1) {
        ecrit("<dl>"); nl();
      }
    } else if ( name.equals("personnage") ) {
      ecrit("<dt>");
    } else if ( name.equals("texte") ) {
      ecrit("<dd>");
    }
  }
  public void endElement (String namespaceURI,
                           String simpleName,
                           String qualifiedName)
  throws SAXException {
    String name = simpleName;
    if (name.equals(""))
      name = qualifiedName;
    if (name.equals("situation") ) {
      ecrit("</i></p>"); nl();
    }
  }
  public void characters (char buf [], int offset, int len)
  throws SAXException {
    String s = new String(buf, offset, len);
    ecrit (s);
    nl();
  }
  private void nl()
  throws SAXException {
    String lineEnd =  System.getProperty("line.separator");
    try {
      dest.write (lineEnd);
    } catch (IOException e) {
      throw new SAXException ("I/O error", e);
    }
  }
  private void ecrit(String s)
  throws SAXException {
    try {
      dest.write (s);
      dest.flush ();
    } catch (IOException e) {
      throw new SAXException ("I/O error", e);
    }
  }
}
 
  

commandes et résultats

$ javac Analyse5.java
$ java Analyse5 dialogue6.xml dialogue6.html
$

 index  suivant