1. Introduction à l’analyse en flux
Historiquement, il existe deux approches en Java pour travailler avec l’XML.
Nous savons déjà que DOM (Document Object Model) construit l’arbre du document en mémoire. Il est pratique de naviguer entre les éléments et de les modifier, mais pour les gros fichiers c’est trop coûteux : la mémoire s’épuise rapidement.
De son côté, SAX (Simple API for XML) traite le fichier séquentiellement et déclenche des événements à la rencontre des balises. C’est économe en mémoire, on peut travailler avec d’immenses documents. Mais écrire des gestionnaires est peu pratique, et il est impossible de revenir en arrière dans la structure.
StAX (Streaming API for XML) est apparu comme un compromis. Il est aussi orienté flux, comme SAX, mais donne au développeur davantage de contrôle : vous « tirez » vous‑même les événements du flux quand c’est nécessaire. Cette approche s’appelle le parsing en mode pull, et elle permet d’écrire un code plus lisible et plus flexible.
Introduction à StAX
StAX (Streaming API for XML) est un parseur XML moderne en flux pour Java, apparu avec JDK 6+.
Idée principale : analyse en mode pull (« parseur qui tire »).
À la différence de SAX, où le parseur appelle vos méthodes lui‑même (modèle push), avec StAX vous contrôlez le processus :
Vous demandez vous‑même au parseur : « Donne‑moi l’événement suivant ! »
Analogie :
SAX — c’est comme la télévision : les événements « coulent » vers vous, vous devez réagir.
StAX — c’est comme un service où vous cliquez vous‑même sur « vidéo suivante » quand vous êtes prêt.
Classes clés de StAX
Pour travailler avec StAX, vous aurez besoin de deux classes principales du package javax.xml.stream :
- XMLInputFactory — fabrique pour créer des parseurs.
- XMLStreamReader — le parseur en flux qui lit l’XML « par morceaux ».
Exemple de code de base :
import javax.xml.stream.*;
import java.io.FileInputStream;
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("data.xml"));
while (reader.hasNext()) {
int event = reader.next();
// traitement de l'événement
}
reader.close();
2. Principe de fonctionnement de StAX : modèle pull
Avec StAX, vous contrôlez vous‑même la lecture de l’XML :
- Ouvrez un flux (par exemple un fichier).
- Créez un XMLStreamReader.
- Dans une boucle, appelez reader.next() pour obtenir l’événement suivant.
- Vérifiez le type d’événement (START_ELEMENT, END_ELEMENT, CHARACTERS, etc.).
- Quand vous arrivez à l’endroit voulu — traitez les données.
- Fermez le parseur.
Schéma de fonctionnement :
flowchart TD
A[Ouvrir XMLStreamReader] --> B{hasNext?}
B -- oui --> C["next()"]
C --> D{Type d’événement ?}
D -- START_ELEMENT --> E[Traitement du début d’élément]
D -- CHARACTERS --> F[Traitement du texte]
D -- END_ELEMENT --> G[Traitement de fin d’élément]
D -- END_DOCUMENT --> H[Terminer]
B -- non --> H
Quels sont les avantages ?
- Vous décidez quand lire l’élément suivant.
- Vous pouvez « vous arrêter » au bon endroit, traiter seulement une partie du fichier.
- Pas besoin d’écrire une foule de gestionnaires comme avec SAX.
3. Types d’événements dans StAX
Lorsque vous appelez reader.next(), le parseur renvoie un type d’événement — un entier (constante de l’interface XMLStreamConstants). Voici les principaux types d’événements :
- START_ELEMENT — début d’un élément XML (<tag>).
- END_ELEMENT — fin d’un élément XML (</tag>).
- CHARACTERS — contenu textuel entre les balises.
- END_DOCUMENT — fin du document.
Exemple de traitement des événements :
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
String name = reader.getLocalName();
System.out.println("Début d’élément: " + name);
break;
case XMLStreamConstants.CHARACTERS:
String text = reader.getText().trim();
if (!text.isEmpty()) {
System.out.println("Texte: " + text);
}
break;
case XMLStreamConstants.END_ELEMENT:
System.out.println("Fin d’élément: " + reader.getLocalName());
break;
}
}
4. Points utiles
Quand utiliser StAX ?
StAX est un choix idéal si :
- Le fichier XML est très volumineux (gigaoctets) et vous ne voulez pas le charger entièrement en mémoire.
- Vous devez traiter seulement une partie du document (par exemple trouver un élément précis et vous arrêter).
- Vous voulez un code simple et clair : StAX est plus simple que SAX et n’exige pas d’écrire une foule de gestionnaires.
Exemples de tâches :
- Import d’un gros fichier XML de données (par exemple export depuis 1C, relevés bancaires, catalogues produits).
- Recherche et traitement des seuls éléments nécessaires (par exemple uniquement <transaction> parmi un million d’enregistrements).
- Transformation de l’XML « à la volée » (par exemple filtrage, agrégation).
Comparaison DOM, SAX et StAX
| Approche | Mémoire | Simplicité | Flexibilité | Quand l’utiliser |
|---|---|---|---|---|
| DOM | Élevée (tout en mémoire) | Très simple | Arbre modifiable | Petits/moyens fichiers, lorsque vous devez modifier l’XML |
| SAX | Minimale | Complexe (gestionnaires d’événements) | Lecture seule, pas de retour en arrière | Très gros fichiers, traitement simple |
| StAX | Minimale | Moyenne (modèle pull) | Lecture par parties, arrêt facile | Gros fichiers quand vous avez besoin de flexibilité et de simplicité |
StAX — le juste milieu :
— N’utilise pas autant de mémoire que DOM.
— N’exige pas de gestionnaires complexes comme SAX.
— Permet de contrôler le processus d’analyse.
5. Exemple : lecture d’un gros fichier XML avec StAX
Supposons que nous ayons un fichier "books.xml" :
<library>
<book>
<title>Java pour débutants</title>
<author>Ivan Ivanov</author>
</book>
<book>
<title>Java avancé</title>
<author>Pyotr Petrov</author>
</book>
<!-- ... beaucoup de livres ... -->
</library>
Objectif : afficher tous les titres de livres.
Code avec StAX :
import javax.xml.stream.*;
import java.io.*;
public class StaxDemo {
public static void main(String[] args) throws Exception {
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("books.xml"));
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT && "title".equals(reader.getLocalName())) {
reader.next(); // passer à CHARACTERS
System.out.println("Livre: " + reader.getText());
}
}
reader.close();
}
}
Avantages :
- Nous ne chargeons pas tout le fichier en mémoire.
- Vous pouvez traiter même un million de livres — le programme ne « plantera » pas.
6. Erreurs courantes avec StAX
Erreur n° 1 : vous avez oublié de fermer le parseur ou le flux. Fermez toujours XMLStreamReader et le flux (InputStream) pour éviter les fuites de ressources.
Erreur n° 2 : vous ne vérifiez pas le type d’événement. Tous les événements ne sont pas des débuts ou des fins d’élément. Vérifiez le type d’événement, sinon vous risquez d’obtenir des chaînes vides ou de manquer des données nécessaires.
Erreur n° 3 : vous n’en tenez pas compte de l’imbrication des éléments. Si la structure XML est complexe (par exemple des livres dans des sections), suivez le niveau d’imbrication actuel pour ne pas confondre les éléments.
Erreur n° 4 : vous utilisez DOM pour de gros fichiers. Si le fichier est volumineux — n’utilisez pas DOM, sinon vous obtiendrez OutOfMemoryError. Pour les gros fichiers — StAX ou SAX uniquement.
Erreur n° 5 : vous ne traitez pas les exceptions. Le travail avec les fichiers et l’XML peut lever des exceptions (XMLStreamException, IOException). Traitez‑les ou propagez‑les.
GO TO FULL VERSION