Technologies internet


Java API pour parser un fichier XML


Voir:

Parser SAX vs parseur DOM

sax vs dom

SAX

SAX a une approche évènementielle du parsing. À chaque composant lu (élément, section CDATA, texte), le noyau du parser fait correspondre un évènement en appelant la méthode correspondante (startElement, handleCDATASection, characters) implémentée dans un handler. Ce handler intercepte en quelque sorte ces évènements et son implémentation est à la charge du développeur.

Faire l'écho du contenu d'un fichier XML avec un parseur SAX

Créer un squelette

public class DomEcho01 {

  public static void main(String argv[]) {
    if (argv.length != 1) {
      System.err.println("Usage: java DomEcho filename");
      System.exit(1);
    }
  }
}

Importer les APIs SAX que nous allons utiliser

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;
Les classes d'exceptions (SAXException, etc.) qui peuvent être déclenchées lorsque le document XML est analysé, sont déjà importées grâce à la clause import org.xml.sax.*;

Préparer E/S

public static void main(String argv[]) {
  if (argv.length != 1) {
    System.err.println("Usage: cmd filename");
    System.exit(1);
  }
  try {
    // Set up output stream
    out = new OutputStreamWriter(System.out, "UTF8");

  } catch (Throwable t) {
      t.printStackTrace();
  }
  System.exit(0);
}

Implémenter l'interface ContentHandler

public class Echo extends DefaultHandler {
  ...
}
Remarques:

Établir un parseur

public static void main(String argv[]) {
  if (argv.length != 1) {
    System.err.println("Usage: cmd filename");
    System.exit(1);
  }

  // Use an instance of ourselves as the SAX event handler
  DefaultHandler handler = new Echo();

  // Use the default (non-validating) parser
  SAXParserFactory factory = SAXParserFactory.newInstance();
  try {
    // Set up output stream
    out = new OutputStreamWriter(System.out, "UTF8");
    // Parse the input
    SAXParser saxParser = factory.newSAXParser();
    saxParser.parse( new File(argv[0]), handler );
  } catch (Throwable t) {
    t.printStackTrace();
  }
  System.exit(0);
}

Écriture dans un fichier de sortie

  static private Writer out;

  private void emit(String s) throws SAXException {
    try {
      out.write(s);
      out.flush();
    } catch (IOException e) {
    throw new SAXException("I/O error", e);
    }
  }
  ...
Remarque: Une exception SAXException peut envelopper une autre exception.
  private void nl() throws SAXException {
    String lineEnd =  System.getProperty("line.separator");
    try {
      out.write(lineEnd);
    } catch (IOException e) {
      throw new SAXException("I/O error", e);
    }
  }

Traitement d'événements


  public void startDocument() throws SAXException {
    emit("<?xml version='1.0' encoding='UTF-8'?>");
    nl();
  }

  public void endDocument() throws SAXException {
    try {
      nl();
      out.flush();
    } catch (IOException e) {
      throw new SAXException("I/O error", e);
    }
  }

  public void startElement(String namespaceURI,
                           String sName, // simple name (localName)
                           String qName, // qualified name
                           Attributes attrs) throws SAXException {
    String eName = sName; // element name
    if ("".equals(eName)) eName = qName; // not namespace-aware
    emit("<" + eName);
    if (attrs != null) {
      for (int i = 0; i < attrs.getLength(); i++) {
        String aName = attrs.getLocalName(i); // Attr name
        if ("".equals(aName)) aName = attrs.getQName(i);
        emit(" ");
        emit(aName+"=\""+attrs.getValue(i)+"\"");
      }
    }
    emit(">");
  }

  public void endElement(String namespaceURI,
                         String sName, // simple name
                         String qName  // qualified name
                        ) throws SAXException {
    String eName = sName; // element name
    if ("".equals(eName)) eName = qName; // not namespace-aware
    emit("</"+eName+">");
  }


  public void characters(char buf[], int offset, int len) throws SAXException {
    String s = new String(buf, offset, len);
    emit(s);
  }

Résultats

L'exécution du programme Echo01.java sur le fichier slideSample01.xml donne les résultats suivants:
<?xml version='1.0' encoding='UTF-8'?>
<slideshow title="Sample Slide Show" date="Date of publication" author="Yours Truly">


    <slide type="all">
      <title>Wake up to WonderWidgets!</title>
    </slide>


    <slide type="all">
      <title>Overview</title>
      <item>Why <em>WonderWidgets</em> are great</item>
      <item>
      <item>Who <em>buys</em> WonderWidgets</item>
    </slide>

</>
Remarque: la méthode characters est responsable d'espaces extra. Le programme Echo01.java peut être modifié pour avoir une sortie plus régulière.