L'API SAX permet d'explorer une ressource XML selon une approche événementielle.

Des gestionnaires spécialisés sont chargés de capturer les événements lancés par l'analyseur SAX.

SAX définit quatre gestionnaires d'événements :

Interface JavaGestionnaire SAXDescription
ContentHandlerDocumentHandlers'occupe des événements concernant les noeuds d'un document XML.
DTDHandlerDTDHandlerprend en compte les événements liés à la définition de type de document.
EntityResolverEntityResolverest sollicitée lorsque l'analyseur SAX atteint des entités externes.
ErrorHandlerErrorHandlerest utilisé pour le traitement des erreurs.

Ces quatres gestionnaires d'événements sont disponibles dans le paquetage org.xml.sax sous la forme d'interfaces.

Ces interfaces fournissent toutes un comportement spécifique que chacune de leurs implémentations doit suivre.

Par exemple, l'interface ContentHandler définit plus d'une dizaine de méthodes qui doivent être invoquées suite à des événements précis.

La méthode startDocument() ou endDocument() est appelée automatiquement par l'analyseur SAX lorsque respectivement, il débute ou il termine, l'analyse d'un document XML.

Dans ce cas, aucune information n'est envoyée sur l'origine de l'événement. Par contre, lorsqu'un élément XML est atteint, la méthode startElement() est appelée et reçoit des informations exploitables sur ce noeud, en l'occurrence, son adresse URI d'espace de noms, son nom local, son nom qualifié et la liste de ses attributs.

public void startElement(
                     String URIEspaceNoms, 
                     String nomLocal, 
                     String nomQalifie, 
                     Attributes attributs){
  System.out.println("Adresse URI : " + URIEspaceNoms);
  System.out.println("Nom local : " + nomLocal);
  System.out.println("Nom qualifié : " + nomQalifie);
  System.out.println("Attributs : " + attributs.getLength());
  for(int i = 0; i < attributs.getLength(); i++){
    System.out.print("\t" + attributs.getQName(i));
    System.out.println(" = " + attributs.getValue(i));
  }
}

Par conséquent, l'API SAX associe chaque type d'événements à une méthode précise, laquelle comporte des paramètres qui expriment l'état spécifique de l'événement d'origine.

Une application SAX doit donc implémenter chacune des méthodes des gestionnaires SAX, pour lesquelles il est nécessaire de gérer des types d'événements déterminés. Les méthodes inutiles devront tout de même être déclarées, mais possèderont un corps vide. Dans le cas contraire, la classe devra être déclarée abstraite.

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;

public class GestionnaireContenu implements ContentHandler {
  public GestionnaireDocument() {
  }
  public void characters(char[] ch, int start, int length) {
    System.out.println("CONTENU TEXTUEL :\n" + new String(ch));
  }
  public void endDocument() {
    System.out.println("FIN DOCUMENT");
  }
  public void endElement(String uri, String localName, String qName) {
    System.out.println("FIN ELEMENT (" + qName + ")");
  }
  public void endPrefixMapping(String prefix) {
    System.out.println("FIN PREFIXE ESPACE DE NOMS (" + prefix + ")");
  }
  public void ignorableWhitespace(char[] ch, int start, int length) {
    System.out.println("ESPACE BLANC : ");
    System.out.println("\tChaine : '" + new String(ch) + "'");
  }
  public void processingInstruction(String target, String data) {
    System.out.println("INSTRUCTION DE TRAITEMENT : ");
    System.out.println("\tCible : " + target);
    System.out.println("\tContenu : " + data);
  }
  public void setDocumentLocator(Locator locator) {
    System.out.println("LOCALISTAION : ");
    System.out.println("\tNom de classe : " + locator.getClass().getName());
    System.out.println("\tN° de colonne : " + locator.getColumnNumber());
    System.out.println("\tN° de ligne : " + locator.getLineNumber());
    System.out.println("\tID Public : " + locator.getPublicId());
    System.out.println("\tID Système : " + locator.getSystemId());
  }
  public void skippedEntity(String name) {
    System.out.println("ENTITE SAUTEE : ");
    System.out.println("\tNom : " + name);
  }
  public void startDocument() {
    System.out.println("DEBUT DOCUMENT");
  }
  public void startElement(String uri, String localName, String qName,
      Attributes attributes) {
    System.out.println("DEBUT ELEMENT (" + qName + ")");
    System.out.println("\tAdresse URI : " + uri);
    System.out.println("\tNom local : " + localName);
    System.out.println("\tNom qualifié : " + qName);
    System.out.println("\tAttributs : " + attributes.getLength());
    for (int i = 0; i < attributes.getLength(); i++) {
      System.out.print("\t\t" + attributes.getQName(i));
      System.out.println(" = " + attributes.getValue(i));
    }
  }
  public void startPrefixMapping(String prefix, String uri) {
    System.out.println("DEBUT PREFIXE ESPACE DE NOMS : ");
    System.out.println("\tPréfixe : " + prefix);
    System.out.println("\tURI : " + uri);
  }
}
Sommaire