2. Création d'un analyseur SAX

2.1. Introduction

La création d’un analyseur se fait en plusieurs étapes. Le développeur doit fournir l’implémentation de plusieurs interfaces. Certaines de ces interfaces ont déjà une implémentation par défaut qui sera peut-être suffisante. Cette création nécessite deux éléments : un analyseur proprement dit, instance de la classe SAXParser, et un objet de gestion des événements ( handler ), qui doit implémenter plusieurs interfaces. Dans la pratique, cet objet sera le plus souvent une extension de la classe DefaultHandler. La classe SAXParser est abstraite, il n’est donc pas possible de l’instancier directement. Pour obtenir un objet de cette classe, on doit passer par une factory , la classe SAXParserFactory. Une factory (usine en anglais), est par convention une classe qui possède une méthode statique newInstance(), qui renvoie une instance de cette classe. Une fois que l’on a cette instance, un appel à la méthode newSAXParser() nous renvoie un objet de type SAXParser.

Exemple 43. Création d'une SAXParserFactory

SAXParserFactory saxParserFactory = SAXParserFactory.newInstance() ;
saxParserFactory.setValidating(true) ;      // ou false si l'on veut un analyseur
                                            // non validant
saxParserFactory.setNameSpaceAware(true) ;  // ou false si l'on ne veut pas 
                                            // prendre en compte 
                                            // les espaces de nom                               
SAXParser saxParser = saxParserFactory.newSAXParser() ;

Cette technique de construction d'instances est très courante en Java. Les classes factory ont en général un nom qui se termine par Factory. La ligne qui permet de rendre l’analyseur validant est facultative si la valeur passée est false. Cet objet de type SAXParser contient un objet de type XMLReader, sur lequel on peut obtenir une référence par appel de la méthode getXMLReader(). On peut configurer cet objet, en fixant pour lui un certain nombre de propriétés standard. Nous verrons l’une de ces propriétés à la fin de cette section. En général, les propriétés par défaut sont suffisantes. Notre objet SAXParser fonctionne avec un gestionnaire, objet de type DefaultHandler. Ce type est une classe concrète, que l’on peut donc instancier. Elle implémente les quatre interfaces ContentHandler, ErrorHandler, DTDHandler et EntityResolver. La bonne façon de faire est donc d’étendre cette classe, et de surcharger les méthodes dont on a besoin.

2.2. Objet DefaultHandler

L'objet que l'on passe à ce parser est un objet qui étend la classe DefaultHandler. Cette classe possède 17 méthodes, appelées comme des callbacks par l'analyseur SAX lorsqu'il rencontre différentes choses dans le document qu'il analyse. Par exemple, au tout début de l'analyse, l'analyseur appelle la méthode startDocument(), ce qui marque le début de l'analyse pour le callback. À chaque fois que l'analyseur rencontre un début d'élément, qu'il s'agisse de l'élément racine ou de tout autre élément XML de notre document, il va appeler la méthode startElemenent(). Cette méthode prend quatre paramètres.
  • String uri : l'URI de l'espace de nom de cet élément ;
  • String localName : le nom local de cet élément, c'est-à-dire sans son préfixe ni son espace de noms ;
  • String qName : le nom qualifié de cet élément, avec son préfixe ;
  • Attributes attributes : les attributs de cet élément, s'il en a.
Si l'analyseur SAX est configuré pour ne pas prendre en compte les espaces de nom, alors les paramètres uri et localName seront systématiquement vides. Le nom qualifé contient le nom de l'élément, avec son préfixe s'il en a un. Dans le cas contraire, deux situations peuvent se présenter.
  • L'élément rencontré est attaché à un espace de nom. L'URI contient alors l'URI de cet espace de noms, le nom local est le nom de l'élément sans son préfixe et le nom qualifié le nom avec son préfixe.
  • L'élément rencontré n'est pas attaché à un espace de nom. Dans ce cas l'URI et le nom local sont vides. Le nom qualifié contient le nom de l'élément, qui, par nature, n'a pas de préfixe.

2.3. Exemple d'analyse d'un fichier

Analysons le fichier simple suivant.

Exemple 44. Un document XML analysé par SAX

<?xml version="1.0" encoding="UTF-8"?>

 <galilee:marins  xmlns:galilee="http://www.galilee.org/marins">
     <galilee:marin  id="12"  lang="FR">
         <nom>Surcouf</nom>
         <prenom>Robert</prenom>
         <age>12</age>
     </galilee:marin>
     <galilee:marin  id="5">
         <nom>Tabarly</nom>
         <prenom>Eric</prenom>
     </galilee:marin>
 </galilee:marins>

Utilisons l'analyseur SAX suivant, extension de la classe DefaultHandler.

Exemple 45. Classe DefaultHandler

// construction de notre handler, classe anonyme
DefaultHandler handler =  new DefaultHandler() {

     public  void startDocument() {
        System.out.println("Début de l'analyse...");
    }

     public  void startElement(String uri, String localName, String qName, Attributes attributes) {
        System.out.println("uri = " + uri);
        System.out.println("local name = " + localName);
        System.out.println("qName = " + qName);
    }
};

Si nous avons configuré l'analyseur SAX de sorte qu'il prend en compte les espaces de nom, le résultat de l'analyse est le suivant.
Début de l'analyse...
uri = http://www.galilee.org/marins
local name = marins
qName = galilee:marins
uri = http://www.galilee.org/marins
local name = marin
qName = galilee:marin
uri = 
local name = nom
qName = nom
uri = 
local name = prenom
qName = prenom
uri = 
local name = age
qName = age
uri = http://www.galilee.org/marins
local name = marin
qName = galilee:marin
uri = 
local name = nom
qName = nom
uri = 
local name = prenom
qName = prenom
On voit sur cette première analyse les différences de comportement de l'analyseur entre les éléments attachés à un espace de nom, et ceux qui ne le sont pas. Voici à présent le résultat de l'analyse avec un analyseur qui ne prend pas en compte les espaces de nom.
Début de l'analyse...
uri = 
local name = 
qName = galilee:marins
uri = 
local name = 
qName = galilee:marin
uri = 
local name = 
qName = nom
uri = 
local name = 
qName = prenom
uri = 
local name = 
qName = age
uri = 
local name = 
qName = galilee:marin
uri = 
local name = 
qName = nom
uri = 
local name = 
qName = prenom
Voyons maintenant ces quatre interfaces et les méthodes qu’elles contiennent.
API Java pour XML
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
Introduction
1. Un peu d'histoire
2. Les API Java pour XML
Un premier exemple
1. Introduction
2. Structure de base d’un fichier XML
2.1. Un fichier XML simple
2.2. Notion d’espaces de noms
3. Un premier code pour lire un fichier XML
3.1. Lecture avec Dom4J
Description d’un document XML
1. Introduction
2. Organisation d'un document XML
2.1. Introduction
2.2. Nœuds dans un document XML
2.3. Relations entre nœuds dans un document XML
2.4. Ordre dans un document
2.5. Valeurs atomiques dans un document XML
2.6. Notion de PCDATA et CDATA
3. Document Type Definition (DTD)
3.1. Attacher un document à une DTD
3.2. Contenu d’une DTD
3.3. Exemple de DTD, analyse de web-app_2_3.dtd
4. XML Schema
4.1. Introduction
4.2. Un premier schéma
4.3. Attacher un document XML à un schéma
4.4. Types simples
4.5. Attribut
4.6. Restriction sur une déclaration
4.7. Types complexes
4.8. Contraindre un contenu simple
Lire et écrire du XML
1. Introduction
2. Utilisation de DOM4J
2.1. Introduction
2.2. Un premier exemple simple
2.3. Organisation de l'API
2.4. Classe Namespace
2.5. Classe QName
2.6. Interface Node
2.7. Interface Branch
2.8. Interface Document
2.9. Interface Element
2.10. Interface Attribute
2.11. Interface Text
3. Utilisation de Xerces
3.1. Introduction
3.2. Présentation de SAX
3.3. Présentation de DOM
Analyseur SAX en Xerces
1. Introduction
2. Création d'un analyseur SAX
2.1. Introduction
2.2. Objet DefaultHandler
2.3. Exemple d'analyse d'un fichier
3. Présentation de l'API
3.1. Interface ContentHandler
3.2. Interface ErrorHandler
3.3. Interface DTDHandler
3.4. Interface EntityResolver
3.5. Interface LexicalHandler
Manipuler un DOM en Xerces
1. Introduction
2. Création d'un DOM
3. Présentation de l'API
3.1. Organisation de l'API
3.2. Interface Node
3.3. Interface NodeList
3.4. Interface Element
3.5. Interface Attr
3.6. Interface CharacterData
3.7. Interface Comment
3.8. Interface CDATASection
3.9. Interface Text
3.10. Interface Entity
3.11. Interface EntityReference
3.12. Interface ProcessingInstruction
3.13. Interface Document
3.14. Interface DocumentFragment
3.15. Interface DocumentType
Interroger un document en XPath
1. Introduction, notion de nœud XML
2. Une première requête XPath
2.1. Un premier document à interroger
2.2. Une première requête
2.3. Forme d'une requête XPath