Een XML-bestand parseren met SAX Parser

1. Overzicht

SAX, ook wel bekend als de Simple API voor XML, wordt gebruikt voor het ontleden van XML-documenten.

In deze tutorial leren we wat SAX is en waarom, wanneer en hoe het moet worden gebruikt.

2. SAX: de eenvoudige API voor XML

SAX is een API die wordt gebruikt om XML-documenten te ontleden. Het is gebaseerd op evenementen gegenereerd tijdens het lezen van het document. Callback-methoden ontvangen die gebeurtenissen. Een aangepaste handler bevat deze callback-methoden.

De API is efficiënt omdat het gebeurtenissen laat vallen direct nadat de callbacks ze hebben ontvangen. Daarom SAX heeft een efficiënt geheugenbeheer, in tegenstelling tot bijvoorbeeld DOM.

3. SAX versus DOM

DOM staat voor Document Object Model. De DOM-parser is niet afhankelijk van gebeurtenissen. Bovendien laadt het het hele XML-document in het geheugen om het te ontleden. SAX is geheugenefficiënter dan DOM.

DOM heeft ook zijn voordelen. DOM ondersteunt bijvoorbeeld XPath. Het maakt het sindsdien ook gemakkelijk om de hele documentboom in één keer te bedienen het document wordt in het geheugen geladen.

4. SAX versus StAX

StAX is recenter dan SAX en DOM. Het staat voor Streaming API voor XML.

Het belangrijkste verschil met SAX is dat StAX maakt gebruik van een trekmechanisme in plaats van het push-mechanisme van SAX (met behulp van callbacks).

Dit betekent dat de controle aan de klant wordt gegeven om te beslissen wanneer de gebeurtenissen moeten worden getrokken. Daarom is er geen verplichting om het hele document te trekken als slechts een deel ervan nodig is.

Het biedt een eenvoudige API om met XML te werken met een geheugenefficiënte manier van parseren.

In tegenstelling tot SAX biedt het geen schemavalidatie als een van zijn functies.

5. Het XML-bestand parseren met een aangepaste handler

Laten we nu de volgende XML gebruiken die de Baeldung-website en zijn artikelen vertegenwoordigt:

   Een XML-bestand parseren met behulp van SAX Parser Lorem ipsum van SAX Parser ... Een XML-bestand parseren met DOM Parser Lorem ipsum van DOM Parser ... Een XML-bestand parseren met StAX Parser Lorem ipsum van StAX ... 

We beginnen met het maken van POJO's voor ons Baeldung wortelelement en zijn kinderen:

openbare klasse Baeldung {privé List articleList; // gebruikelijke getters en setters} 
openbare klasse BaeldungArticle {private String-titel; privé String-inhoud; // gebruikelijke getters en setters} 

We gaan door met het maken van het BaeldungHandler. Deze klasse implementeert de callback-methoden die nodig zijn om de gebeurtenissen vast te leggen.

We overschrijven vier methoden uit de superklasse DefaultHandler, elk kenmerkend voor een evenement:

    • karakters (char [], int, int) ontvangt tekens met grenzen. We converteren ze naar een Draad en sla het op in een variabele van BaeldungHandler
    • startDocument () wordt aangeroepen wanneer het parseren begint - we zullen het gebruiken om onze Baeldung voorbeeld
    • startElement () wordt aangeroepen wanneer het parseren begint voor een element - we zullen het gebruiken om een ​​van beide te construeren Lijst of BaeldungArtikel gevallen - qNaam helpt ons het onderscheid te maken tussen beide typen
    • endElement () wordt aangeroepen wanneer het ontleden eindigt voor een element - dit is wanneer we de inhoud van de tags aan hun respectievelijke variabelen toewijzen

Nu alle callbacks zijn gedefinieerd, kunnen we nu het BaeldungHandler klasse:

openbare klasse BaeldungHandler breidt DefaultHandler {privé statische laatste String ARTIKEL = "artikelen" uit; private static final String ARTICLE = "article"; private static final String TITLE = "title"; private static final String CONTENT = "content"; particuliere Baeldung-website; private String elementValue; @Override openbare ongeldige tekens (char [] ch, int start, int length) gooit SAXException {elementValue = nieuwe String (ch, start, lengte); } @Override public void startDocument () gooit SAXException {website = new Baeldung (); } @Override public void startElement (String uri, String lName, String qName, Attributes attr) gooit SAXException {switch (qName) {case ARTIKELEN: website.articleList = new ArrayList (); breken; case ARTIKEL: website.articleList.add (nieuw BaeldungArticle ()); }} @Override public void endElement (String uri, String localName, String qName) genereert SAXException {switch (qName) {case TITLE: latestArticle (). Title = elementValue; breken; case CONTENT: latestArticle (). content = elementValue; breken; }} privé BaeldungArticle latestArticle () {List articleList = website.articleList; int latestArticleIndex = articleList.size () - 1; retourneer articleList.get (latestArticleIndex); } openbare Baeldung getWebsite () {retourwebsite; }} 

Stringconstanten zijn ook toegevoegd om de leesbaarheid te vergroten. Een methode om het laatst gevonden artikel op te halen is ook handig. Ten slotte hebben we een vangstof nodig voor de Baeldung voorwerp.

Merk op dat het bovenstaande niet thread-safe is, omdat we de status vasthouden tussen de methodeaanroepen.

6. Testen van de parser

Om de parser te testen, instantiëren we het SaxFactory, de SaxParser en ook de BaeldungHandler:

SAXParserFactory fabriek = SAXParserFactory.newInstance (); SAXParser saxParser = factory.newSAXParser (); SaxParserMain.BaeldungHandler baeldungHandler = nieuwe SaxParserMain.BaeldungHandler (); 

Daarna zullen we het XML-bestand ontleden en stellen dat het object alle verwachte geparseerde elementen bevat:

saxParser.parse ("src / test / resources / sax / baeldung.xml", baeldungHandler); SaxParserMain.Baeldung resultaat = baeldungHandler.getWebsite (); assertNotNull (resultaat); Lijstartikelen = result.getArticleList (); assertNotNull (artikelen); assertEquals (3, artikelen.size ()); SaxParserMain.BaeldungArticle articleOne = artikelen.get (0); assertEquals ("Een XML-bestand parseren met SAX Parser", articleOne.getTitle ()); assertEquals ("SAX Parser's Lorem ipsum ...", articleOne.getContent ()); SaxParserMain.BaeldungArticle articleTwo = artikelen.get (1); assertEquals ("Een XML-bestand parseren met DOM-parser", articleTwo.getTitle ()); assertEquals ("DOM Parser's Lorem ipsum ...", articleTwo.getContent ()); SaxParserMain.BaeldungArticle articleThree = artikelen.get (2); assertEquals ("Een XML-bestand parseren met behulp van StAX Parser", articleThree.getTitle ()); assertEquals ("Lorem ipsum van StAX Parser ...", articleThree.getContent ()); 

Zoals verwacht, de baeldung is correct geparseerd en bevat de verwachte subobjecten.

7. Conclusie

We hebben net ontdekt hoe we SAX kunnen gebruiken om XML-bestanden te parseren. Het is een krachtige API die een kleine geheugenvoetafdruk genereert in onze applicaties.

Zoals gewoonlijk is de code voor dit artikel beschikbaar op GitHub.