Accueil
Accueil
Le
Club
Delphi
Kylix
C
C++
Java
J2EE
DotNET
& C#
Visual
Basic
Access
Pascal
Dev
Web
PHP
ASP
XML
UML
SQL
SGBD
Win
Linux
Autres



Comment fonctionne l'API SAX ?
auteur : Ioan Calapodescu
Architecture d'une application utilisant SAX :

Source image : J2EE 1.4 Tutorial
Pour commencer, l'application récupère un parseur (javax.xml.parsers.SAXParser) à partir d'une fabrique de parseurs (javax.xml.parsers.SAXParserFactory).

Ce parseur parcourt le document XML grâce à un lecteur (org.xml.sax.XMLReader). Ce dernier contient plusieurs gestionnaires (ou handlers). Ce sont ces différents gestionnaires qui sont chargés du traitement des "événements" lors du parsing. Voici les quatre principaux types de handlers (interfaces du package org.xml.sax) :

  • Gestionnaire de Contenu : Le ContentHandler est chargé des événements comme le début ou la fin du document, l'ouverture ou a fermeture de balises ou encore la lecture de caractères.
  • Gestionnaire d'Erreurs : Le ErrorHandler va traiter les trois types d'erreurs possibles lors du parsing : les erreurs simples, les erreurs fatales et les warnings.
  • Gestionnaire de DTD : Le DTDHandler (Document Type Definition) gère les événements relatifs aux DTD.
  • Gestionnaire d'entités externes : L'EntityResolver est chargé de gérer les entités externes, en fournissant une InputSource adéquate.


Doit-on implémenter les quatre types de handlers ?
auteur : Ioan Calapodescu
Non, ce n'est pas nécessaire. Il faut utiliser la classe DefaultHandler du package org.xml.sax.helpers.

Le fonctionnement de cette classe peut être comparé à celui des adapters pour les listeners (AWT et Swing). C'est à dire que cette classe propose une implémentation par défaut des quatres types de gestionnaires.

Vous avez simplement besoin d'étendre cette classe afin d'implémenter les méthodes qui vous sont utiles. Pour un exemple, regardez : Comment parser un XML avec SAX ?.

Vous pouvez aussi regarder du côté de la classe org.xml.sax.ext.DefaultHandler2, qui propose en plus des quatre handlers de base une implémentation par défaut de DeclHandler, EntityResolver2 et LexicalHandler. Ces trois gestionnaires sont des extensions pour SAX2.

lien : Comment parser un XML avec SAX ?

Comment créer un parseur avec SAX ?
auteur : Ioan Calapodescu
Voici un exemple de création de parseur SAX utilisant un DefaultHandler.

import org.xml.sax.*; import org.xml.sax.helpers.*; import javax.xml.parsers.*; import java.io.*; public class ExempleSAX { public static void main(String[] args){ try{ // création d'une fabrique de parseurs SAX SAXParserFactory fabrique = SAXParserFactory.newInstance(); // création d'un parseur SAX SAXParser parseur = fabrique.newSAXParser(); // lecture d'un fichier XML avec un DefaultHandler File fichier = new File("./ExempleSAX.xml"); DefaultHandler gestionnaire = new DefaultHandler(); parseur.parse(fichier, gestionnaire); }catch(ParserConfigurationException pce){ System.out.println("Erreur de configuration du parseur"); System.out.println("Lors de l'appel à newSAXParser()"); }catch(SAXException se){ System.out.println("Erreur de parsing"); System.out.println("Lors de l'appel à parse()"); }catch(IOException ioe){ System.out.println("Erreur d'entrée/sortie"); System.out.println("Lors de l'appel à parse()"); } } }
Ce code ne fait "rien", dans le sens que vous n'aurez aucun effet visible lors de son exécution. Cet exemple met juste en évidence l'obtention du parseur et les types d'exception susceptibles d'être levées. Pour un exemple d'implémentation de DefaultHandler regardez : Comment parser un XML avec SAX ?.

Voici quelques propriétés du parseur (SAXParser) que vous pouvez spécifier à la fabrique (SAXParserFactory) :

  • setValidating(boolean) : indique si les parseurs produits par la fabrique doivent valider la DTD. Par défaut, cette valeur est false.
  • setSchema(Schema) : indique que les parseurs produits par la fabrique doivent valider le document XML selon un schéma XML W3C.
  • setFeature(String, boolean) : permet d'indiquer une propriété particulière pour les parseurs produits par la fabrique. Pour une liste de ces propriétés, regardez le lien ci-dessous.
  • setNamespaceAware(boolean) : indique si les parseurs, produits par la fabrique, supportent les espaces de nommage XML.

Pour finir, vous pouvez configurer encore plus profondément votre parseur avec la méthode setProperty(String, Object) de la classe SAXParser.

Pour une liste des features et properties, vous pouvez regarder la description du package org.xml.sax.

Pour un exemple simple (affichage sur la sortie standard du XML) téléchargez le fichier ci-dessous.

Pour un exemple plus complet, regardez : Comment parser un XML avec SAX ?.

lien : Comment parser un XML avec SAX ?
téléchargement : ExempleSAX.zip

Comment parser un XML avec SAX ?
auteur : Ioan Calapodescu
Imaginons le fichier XML suivant, qui représente un "annuaire" :

Annuaire XML
<annuaire> <personne id="0"> <nom>nom0</nom> <prenom>prenom0</prenom> <adresse>adresse0</adresse> </personne> <personne id="1"> <nom>nom1</nom> <prenom>prenom1</prenom> <adresse>adresse1</adresse> </personne> </annuaire>
Voici un simple JavaBean Personne nous permettant de représenter une entrée dans cet annuaire :

Personne
public class Personne{ private int id; private String nom, prenom, adresse; public Personne(){} public int getId(){return id;} public String getNom(){return nom;} public String getPrenom(){return prenom;} public String getAdresse(){return adresse;} public void setId(int id){this.id = id;} public void setNom(String nom){this.nom = nom;} public void setPrenom(String prenom){this.prenom = prenom;} public void setAdresse(String adresse){this.adresse = adresse;} public String toString(){ return new StringBuffer("Nom : ").append(nom).append(", ") .append("Prenom : ").append(prenom).append(", ") .append("Adresse : ").append(adresse) .toString(); } }
Finalement, voici le DefaultHandler nous permettant le parsing du XML. Le parsing va simplement récupérer une List de Personne.

PersonneHandler
public class PersonneHandler extends DefaultHandler{ //résultats de notre parsing private List<Personne> annuaire; private Personne personne; //flags nous indiquant la position du parseur private boolean inAnnuaire, inPersonne, inNom, inPrenom, inAdresse; //buffer nous permettant de récupérer les données private StringBuffer buffer; // simple constructeur public PersonneHandler(){ super(); } //détection d'ouverture de balise public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException{ if(qName.equals("annuaire")){ annuaire = new LinkedList<Personne>(); inAnnuaire = true; }else if(qName.equals("personne")){ personne = new Personne(); try{ int id = Integer.parseInt(attributes.getValue("id")); personne.setId(id); }catch(Exception e){ //erreur, le contenu de id n'est pas un entier throw new SAXException(e); } inPersonne = true; }else { buffer = new StringBuffer(); if(qName.equals("nom")){ inNom = true; }else if(qName.equals("prenom")){ inPrenom = true; }else if(qName.equals("adresse")){ inAdresse = true; }else{ //erreur, on peut lever une exception throw new SAXException("Balise "+qName+" inconnue."); } } } //détection fin de balise public void endElement(String uri, String localName, String qName) throws SAXException{ if(qName.equals("annuaire")){ inAnnuaire = false; }else if(qName.equals("personne")){ annuaire.add(personne); personne = null; inPersonne = false; }else if(qName.equals("nom")){ personne.setNom(buffer.toString()); buffer = null; inNom = false; }else if(qName.equals("prenom")){ personne.setPrenom(buffer.toString()); buffer = null; inPrenom = false; }else if(qName.equals("adresse")){ personne.setAdresse(buffer.toString()); buffer = null; inAdresse = false; }else{ //erreur, on peut lever une exception throw new SAXException("Balise "+qName+" inconnue."); } } //détection de caractères public void characters(char[] ch,int start, int length) throws SAXException{ String lecture = new String(ch,start,length); if(buffer != null) buffer.append(lecture); } //début du parsing public void startDocument() throws SAXException { System.out.println("Début du parsing"); } //fin du parsing public void endDocument() throws SAXException { System.out.println("Fin du parsing"); System.out.println("Resultats du parsing"); for(Personne p : annuaire){ System.out.println(p); } } }
L'utilisation de ces trois éléments se fait simplement comme ceci :

SAXParserFactory fabrique = SAXParserFactory.newInstance(); SAXParser parseur = fabrique.newSAXParser(); File fichier = new File("./ExempleSAX.xml"); DefaultHandler gestionnaire = new PersonneHandler(); parseur.parse(fichier, gestionnaire);
Il existe des API plus avancées que SAX pour lier des fichiers XML et des Object Java. L'exemple ci-dessus sert juste de démonstration.

téléchargement : PersonneHandler.zip

Comment gérer les erreurs durant le parsing ?
auteur : Ioan Calapodescu
Au niveau du document XML, il existe deux types d'erreurs possibles.

  • Le document peut être non valide. Dans ce cas, le document n'obéit pas à la DTD ou au schéma qu'on lui a imposé.
  • Le document peut être mal formé. Dans ce cas, il y a simplement une erreur par rapport au standard XML lui même. Par exemple, des balises mal fermées ou se chevauchant.

Par contre, au niveau du parseur SAX, il existe trois niveaux d'erreurs. Ces trois niveaux d'erreurs sont représentées au niveau du Gestionnaire d'Erreurs (ErrorHandler) :

  • Erreur fatale (fatalError(SAXParseException exception) throws SAXException) : Cette erreur ne peut être récupérée. C'est le cas par exemple pour un document mal formé. Après ce type d'erreur, le parseur SAX arrête son travail.
  • Erreur (error(SAXParseException exception) throws SAXException) : Cette erreur peut être récupérée, c'est à dire que le parseur SAX peut continuer à traiter le reste du document XML. Ce genre d'erreur peut se produire lors d'une violation d'une contrainte imposée par la DTD ou le schéma.
  • Warning (warning(SAXParseException exception) throws SAXException) : C'est un simple avertissement. Après celà, le parseur SAX continue le parsing du document.

Pour plus d'information sur ces erreurs, vous pouvez regarder XML 1.0 W3C Recommendation. Par défaut (cf. DefautHandler), seules les erreurs fatales sont "traitées".

Voici un exemple d'implémentation de ErrorHandler. Cet exemple détaille sur la sortie standard les erreurs simples et warnings et lève une SAXException pour les erreurs fatales :

protected String message(SAXParseException e){ String message = "Message : "+e.getMessage()+"\n"; message += "Ligne "+e.getLineNumber()+", colonne "+e.getColumnNumber()+"\n"; message += "Public id : "+e.getPublicId()+"\n"; message += "System id : "+e.getSystemId(); return message; } protected void printSAXException(SAXParseException e){ System.out.println(message(e)); if(e.getException() != null){ e.getException().printStackTrace(); } } public void warning(SAXParseException exception) throws SAXException{ System.out.println("*** Warning ***"); printSAXException(exception); } public void error(SAXParseException exception) throws SAXException{ System.out.println("*** Erreur ***"); printSAXException(exception); } public void fatalError(SAXParseException exception) throws SAXException{ String message = "*** Erreur fatale ***\n"; message += message(exception); SAXException se = new SAXException(message, exception); throw se; }
Pour un exemple d'utilisation, téléchargez le fichier ci-dessous.

téléchargement : ExempleErrorHandlerSAX.zip

Ou trouver plus d'informations sur SAX ?
auteur : Ioan Calapodescu
Pour de plus amples informations sur SAX, vous pouvez regarder l'excellent tutoriel de Sébatien Méric : Lecture d'un flux XML via SAX.

Vous pouvez avoir d'autres informations sur l'utilisation de SAX, en anglais cette fois ci, dans le J2EE 1.4 Tutorial.

lien :  Cours Java - Lecture d'un flux XML via SAX
lien :  J2EE 1.4 Tutorial


Consultez les autres F.A.Q's

Les codes sources présentés sur cette page sont libres de droits, et vous pouvez les utiliser à votre convenance. Pour le reste, ce document constitue une oeuvre intellectuelle protégée par les droits d'auteurs.

Ce document issu de http://www.developpez.com est soumis à deux licences, en fonction des contributeurs :

- Les contributions de Clément Cunin et Johann Heymes sont soumises aux termes de la la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies des contributions de Clément Cunin et Johann Heymes tant que cette note apparaît clairement :
"Ce document issu de http://www.developpez.com est soumis à la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement".

- Pour ce qui est des autres contributions : Copyright © 2004 Developpez LLC : Tous droits réservés Developpez LLC. Aucune reproduction, ne peux en être faite sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vos questions techniques : forum d'entraide PHP - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Copyright 2000..2004 www.developpez.com