Voorbeeld van Java SAX-parser

SAX-parser in Java biedt een API voor het parseren van XML-documenten. De SAX-parser verschilt van de DOM-parser omdat deze niet het volledige XML-bestand in het geheugen laadt en het XML-document sequentieel leest.

SAX-parser

javax.xml.parsers.SAXParser biedt een methode om XML-documenten te parseren met behulp van gebeurtenishandlers. Deze klasse implementeert de XMLReader-interface en biedt overbelaste versies van parse()-methoden om XML-documenten te lezen vanuit een bestand, InputStream, SAX InputSource en String URI. Het feitelijke parsen wordt gedaan door de Handler-klasse. We moeten onze eigen handler-klasse maken om het XML-document te parseren. We moeten de org.xml.sax.ContentHandler-interface implementeren om onze eigen handler-klassen te maken. Deze interface bevat callback-methoden die meldingen ontvangen wanneer een gebeurtenis optreedt. Bijvoorbeeld StartDocument, EndDocument, StartElement, EndElement, CharacterData, enz. org.xml.sax.helpers.DefaultHandler biedt een standaardimplementatie van de ContentHandler-interface en we kunnen deze klasse uitbreiden om onze eigen handler te maken. Het is raadzaam om deze klasse uit te breiden omdat we mogelijk slechts enkele van de methoden nodig hebben om te implementeren. Door deze klasse uit te breiden, blijft onze code schoner en onderhoudbaarder.

SAX-parser voorbeeld

Laten we nu naar het voorbeeldprogramma van de SAX-parser springen. Ik zal later verschillende functies gedetailleerd uitleggen. 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>

Dus we hebben een XML-bestand ergens opgeslagen in het bestandssysteem en door ernaar te kijken, kunnen we concluderen dat het een lijst van werknemers bevat. Elke werknemer heeft het attribuut id en de velden leeftijd, naam, geslacht en rol. We zullen een SAX-parser gebruiken om deze XML te parseren en een lijst van werknemersobjecten te maken. Hier is het werknemersobject dat het werknemerselement uit XML vertegenwoordigt.

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;
    }
    
}

Laten we onze eigen SAX Parser Handler-klasse maken die de klasse DefaultHandler uitbreidt.


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 {

	// Lijst om werknemersobjecten vast te houden
	private List empList = null;
	private Employee emp = null;
	private StringBuilder data = null;

	// getter-methode voor lijst met werknemers
	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")) {
			// creëer een nieuwe werknemer en plaats deze in Map
			String id = attributes.getValue("id");
			// initialiseer het werknemersobject en stel het id-attribuut in
			emp = new Employee();
			emp.setId(Integer.parseInt(id));
			// initialiseer lijst
			if (empList == null)
				empList = new ArrayList<>();
		} else if (qName.equalsIgnoreCase("name")) {
			// stel booleaanse waarden in voor velden, zal worden gebruikt bij het instellen van werknemervariabelen
			bName = true;
		} else if (qName.equalsIgnoreCase("age")) {
			bAge = true;
		} else if (qName.equalsIgnoreCase("gender")) {
			bGender = true;
		} else if (qName.equalsIgnoreCase("role")) {
			bRole = true;
		}
		// maak de gegevenscontainer
		data = new StringBuilder();
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		if (bAge) {
			// leeftijdselement, stel leeftijd van werknemer in
			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")) {
			// voeg werknemersobject toe aan lijst
			empList.add(emp);
		}
	}

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

MijnHandler bevat de lijst van het Werknemer-object als een veld met alleen een getter-methode. De Werknemer-objecten worden toegevoegd in de methoden van de gebeurtenishandler. Ook hebben we een werknemersveld dat zal worden gebruikt om een werknemersobject te maken en zodra alle velden zijn ingesteld, voeg het toe aan de lijst met werknemers.

SAX-parsermethoden om over te schrijven

De belangrijke methoden om te overschrijven zijn startElement(), endElement() en characters(). SAXParser begint het document te parseren, wanneer een startelement wordt gevonden, wordt de methode startElement() aangeroepen. We overschrijven deze methode om boolean-variabelen in te stellen die worden gebruikt om het element te identificeren. We gebruiken deze methode ook om telkens wanneer het Employee-startelement wordt gevonden, een nieuw Employee-object te maken. Controleer hoe het id-attribuut hier wordt gelezen om het veld id van het Employee-object in te stellen. De methode characters() wordt aangeroepen wanneer karaktergegevens worden gevonden door SAXParser binnen een element. Merk op dat de SAX-parser de gegevens in meerdere stukken kan verdelen en de methode characters() meerdere keren kan aanroepen (lees de documentatie van de characters()-methode van de ContentHandler-klasse). Daarom gebruiken we StringBuilder om deze gegevens bij te houden met behulp van de append()-methode. Het endElement()-gedeelte is de plaats waar we de gegevens van de StringBuilder gebruiken om eigenschappen van het Employee-object in te stellen en het Employee-object aan de lijst toe te voegen telkens wanneer we het eindetiket van Employee vinden. Hieronder staat het testprogramma dat MyHandler gebruikt om bovenstaande XML naar een lijst van Employee-objecten te parseren.

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);
        //Ontvang lijst met werknemers
        List empList = handler.getEmpList();
        //print werknemersinformatie
        for(Employee emp : empList)
            System.out.println(emp);
    } catch (ParserConfigurationException | SAXException | IOException e) {
        e.printStackTrace();
    }
    }

}

Hier is de uitvoer van het bovenstaande programma.

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 biedt fabrieksmethoden om de instantie van SAXParser te krijgen. We geven een File-object door aan de parse-methode samen met een instantie van MyHandler om de callback-gebeurtenissen af te handelen. SAXParser is in het begin een beetje verwarrend, maar als je werkt aan een groot XML-document, biedt het een efficiëntere manier om XML te lezen dan DOM Parser. Dat is alles voor SAX Parser in Java.

Je kunt het project downloaden van onze GitHub Repository.

Referentie: SAXParser, DefaultHandler

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