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