Exemple de parseur SAX Java

Le parseur SAX en Java offre une API pour analyser les documents XML. Le parseur SAX est différent du parseur DOM car il ne charge pas l’intégralité du XML en mémoire et lit le document XML séquentiellement.

Parseur SAX

javax.xml.parsers.SAXParser fournit une méthode pour analyser un document XML en utilisant des gestionnaires d’événements. Cette classe implémente l’interface XMLReader et fournit des versions surchargées des méthodes parse() pour lire un document XML à partir d’un fichier, d’un InputStream, d’une source d’entrée SAX et d’une URI de chaîne. L’analyse réelle est effectuée par la classe Handler. Nous devons créer notre propre classe de gestionnaire pour analyser le document XML. Nous devons implémenter l’interface org.xml.sax.ContentHandler pour créer nos propres classes de gestionnaire. Cette interface contient des méthodes de rappel qui reçoivent une notification lorsqu’un événement se produit. Par exemple, StartDocument, EndDocument, StartElement, EndElement, CharacterData, etc. org.xml.sax.helpers.DefaultHandler fournit une implémentation par défaut de l’interface ContentHandler et nous pouvons étendre cette classe pour créer notre propre gestionnaire. Il est conseillé d’étendre cette classe car nous pourrions avoir besoin que de quelques-unes des méthodes à implémenter. Étendre cette classe permettra de garder notre code plus propre et maintenable.

Exemple de parseur SAX

Passons maintenant à l’exemple de programme de parseur SAX, je vais expliquer différentes fonctionnalités en détail plus tard. employees.xml

<?xml version="1.0" encoding="UTF-8"?>
<Employees>
	<Employee id="1">
		<age>29</age>
		<name>Pankaj</name>
		<gender>Male</gender>
		<role>Java Developer</role>
	</Employee>
	<Employee id="2">
		<age>35</age>
		<name>Lisa</name>
		<gender>Female</gender>
		<role>CEO</role>
	</Employee>
	<Employee id="3">
		<age>40</age>
		<name>Tom</name>
		<gender>Male</gender>
		<role>Manager</role>
	</Employee>
	<Employee id="4">
		<age>25</age>
		<name>Meghna</name>
		<gender>Female</gender>
		<role>Manager</role>
	</Employee>
</Employees>

Donc, nous avons un fichier XML stocké quelque part dans le système de fichiers et en le regardant, nous pouvons conclure qu’il contient une liste d’employés. Chaque employé a l’attribut id et les champs age, name, gender et role. Nous utiliserons un analyseur SAX pour analyser ce XML et créer une liste d’objets Employee. Voici l’objet Employee représentant l’élément Employee du XML.

package com.journaldev.xml;

public class Employee {
    private int id;
    private String name;
    private String gender;
    private int age;
    private String role;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    
    @Override
    public String toString() {
        return "Employee:: ID="+this.id+" Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender +
                " Role=" + this.role;
    }
    
}

Créons notre propre classe de gestionnaire SAX en étendant la classe DefaultHandler.


package com.journaldev.xml.sax;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.journaldev.xml.Employee;

public class MyHandler extends DefaultHandler {

	// Liste pour contenir des objets Employee
	private List empList = null;
	private Employee emp = null;
	private StringBuilder data = null;

	// Méthode getter pour la liste des employés
	public List getEmpList() {
		return empList;
	}

	boolean bAge = false;
	boolean bName = false;
	boolean bGender = false;
	boolean bRole = false;

	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

		if (qName.equalsIgnoreCase("Employee")) {
			// Créez un nouvel employé et placez-le dans la carte
			String id = attributes.getValue("id");
			// Initialisez l'objet Employee et définissez l'attribut id
			emp = new Employee();
			emp.setId(Integer.parseInt(id));
			// Initialisez la liste
			if (empList == null)
				empList = new ArrayList<>();
		} else if (qName.equalsIgnoreCase("name")) {
			// Définissez des valeurs booléennes pour les champs, qui seront utilisées pour définir les variables Employee
			bName = true;
		} else if (qName.equalsIgnoreCase("age")) {
			bAge = true;
		} else if (qName.equalsIgnoreCase("gender")) {
			bGender = true;
		} else if (qName.equalsIgnoreCase("role")) {
			bRole = true;
		}
		// Créez le conteneur de données
		data = new StringBuilder();
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		if (bAge) {
			// élément age, définissez l'âge de l'employé
			emp.setAge(Integer.parseInt(data.toString()));
			bAge = false;
		} else if (bName) {
			emp.setName(data.toString());
			bName = false;
		} else if (bRole) {
			emp.setRole(data.toString());
			bRole = false;
		} else if (bGender) {
			emp.setGender(data.toString());
			bGender = false;
		}
		
		if (qName.equalsIgnoreCase("Employee")) {
			// Ajoutez l'objet Employee à la liste
			empList.add(emp);
		}
	}

	@Override
	public void characters(char ch[], int start, int length) throws SAXException {
		data.append(new String(ch, start, length));
	}
}

MyHandler contient la liste de l’objet Employee en tant que champ avec une méthode getter uniquement. Les objets Employee sont ajoutés dans les méthodes de gestionnaire d’événements. De plus, nous avons un champ Employee qui sera utilisé pour créer un objet Employee et une fois que tous les champs sont définis, l’ajouter à la liste des employés.

Méthodes à remplacer du parseur SAX

Les méthodes importantes à remplacer sont startElement(), endElement() et characters(). SAXParser commence l’analyse du document lorsqu’un élément de début est trouvé, la méthode startElement() est appelée. Nous remplaçons cette méthode pour définir des variables booléennes qui seront utilisées pour identifier l’élément. Nous utilisons également cette méthode pour créer un nouvel objet Employee chaque fois qu’un élément de début d’Employee est trouvé. Vérifiez comment l’attribut id est lu ici pour définir le champ id de l’objet Employee. La méthode characters() est appelée lorsque des données de caractères sont trouvées par SAXParser à l’intérieur d’un élément. Notez que le parseur SAX peut diviser les données en plusieurs morceaux et appeler la méthode characters() plusieurs fois (lisez la documentation de la méthode characters() de la classe ContentHandler). C’est pourquoi nous utilisons StringBuilder pour conserver ces données en utilisant la méthode append(). La méthode endElement() est l’endroit où nous utilisons les données de StringBuilder pour définir les propriétés de l’objet employee et ajouter l’objet Employee à la liste chaque fois que nous trouvons la balise de fin d’Employee. Voici le programme de test qui utilise MyHandler pour analyser le XML ci-dessus en liste d’objets Employee.

package com.journaldev.xml.sax;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import com.journaldev.xml.Employee;

public class XMLParserSAX {

    public static void main(String[] args) {
    SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
    try {
        SAXParser saxParser = saxParserFactory.newSAXParser();
        MyHandler handler = new MyHandler();
        saxParser.parse(new File("/Users/pankaj/employees.xml"), handler);
        //Obtenir la liste des employés
        List empList = handler.getEmpList();
        //afficher les informations sur l'employé
        for(Employee emp : empList)
            System.out.println(emp);
    } catch (ParserConfigurationException | SAXException | IOException e) {
        e.printStackTrace();
    }
    }

}

Voici la sortie du programme ci-dessus.

Employee:: ID=1 Name=Pankaj Age=29 Gender=Male Role=Java Developer
Employee:: ID=2 Name=Lisa Age=35 Gender=Female Role=CEO
Employee:: ID=3 Name=Tom Age=40 Gender=Male Role=Manager
Employee:: ID=4 Name=Meghna Age=25 Gender=Female Role=Manager

SAXParserFactory fournit des méthodes de fabrique pour obtenir l’instance de SAXParser. Nous passons un objet File à la méthode parse ainsi qu’une instance de MyHandler pour gérer les événements de rappel. SAXParser est un peu déroutant au début, mais si vous travaillez sur un grand document XML, il offre un moyen plus efficace de le lire que DOM Parser. C’est tout pour SAX Parser en Java.

Vous pouvez télécharger le projet depuis notre référentiel GitHub .

Référence : SAXParser , DefaultHandler

Source:
https://www.digitalocean.com/community/tutorials/java-sax-parser-example