Analysieren einer XML-Datei mit SAX Parser

1. Übersicht

SAX, auch als Simple API for XML bekannt , wird zum Parsen von XML-Dokumenten verwendet.

In diesem Tutorial erfahren Sie, was SAX ist und warum, wann und wie es verwendet werden sollte.

2. SAX : Die einfache API für XML

SAX ist eine API zum Parsen von XML-Dokumenten. Es basiert auf Ereignissen, die beim Lesen des Dokuments generiert wurden. Rückrufmethoden empfangen diese Ereignisse. Ein benutzerdefinierter Handler enthält diese Rückrufmethoden.

Die API ist effizient, da Ereignisse direkt nach dem Empfang durch die Rückrufe gelöscht werden. Daher verfügt SAX im Gegensatz zu beispielsweise DOM über eine effiziente Speicherverwaltung .

3. SAX vs DOM

DOM steht für Document Object Model. Der DOM-Parser ist nicht auf Ereignisse angewiesen . Darüber hinaus wird das gesamte XML-Dokument in den Speicher geladen, um es zu analysieren. SAX ist speichereffizienter als DOM.

DOM hat auch seine Vorteile. Beispielsweise unterstützt DOM XPath. Es macht es auch einfach, den gesamten Dokumentbaum auf einmal zu bearbeiten, da das Dokument in den Speicher geladen wird .

4. SAX vs StAX

StAX ist neuer als SAX und DOM. Es steht für Streaming API for XML .

Der Hauptunterschied zu SAX besteht darin, dass StAX anstelle des Push-Mechanismus von SAX einen Pull-Mechanismus verwendet (mithilfe von Rückrufen).

Dies bedeutet, dass der Client die Kontrolle erhält, um zu entscheiden, wann die Ereignisse abgerufen werden müssen. Daher besteht keine Verpflichtung, das gesamte Dokument abzurufen, wenn nur ein Teil davon benötigt wird.

Es bietet eine einfache API für die Arbeit mit XML mit einer speichereffizienten Methode zum Parsen.

Im Gegensatz zu SAX bietet es keine Schemaüberprüfung als eine seiner Funktionen.

5. Analysieren der XML-Datei mit einem benutzerdefinierten Handler

Verwenden wir nun das folgende XML, das die Baeldung-Website und ihre Artikel darstellt:

   Parsing an XML File Using SAX Parser SAX Parser's Lorem ipsum...   Parsing an XML File Using DOM Parser DOM Parser's Lorem ipsum...   Parsing an XML File Using StAX Parser StAX's Lorem ipsum...   

Wir beginnen mit der Erstellung von POJOs für unser Baeldung- Wurzelelement und seine untergeordneten Elemente:

public class Baeldung { private List articleList; // usual getters and setters } 
public class BaeldungArticle { private String title; private String content; // usual getters and setters } 

Wir werden fortfahren, indem wir den BaeldungHandler erstellen . Diese Klasse implementiert die Rückrufmethoden, die zum Erfassen der Ereignisse erforderlich sind.

Wir überschreiben vier Methoden aus der Oberklasse DefaultHandler, die jeweils ein Ereignis charakterisieren:

    • Zeichen (char [], int, int) empfangen Zeichen mit Grenzen. Wir werden sie in einen String konvertieren und in einer Variablen von BaeldungHandler speichern
    • startDocument () wird aufgerufen, wenn die Analyse beginnt - wir werden es verwenden, um unsere Baeldung- Instanz zu erstellen
    • Startelement () wird aufgerufen , wenn das Parsen für ein Element beginnt - wir verwenden werden , entweder zu konstruieren Liste oder BaeldungArticle Instanzen - QNAME hilft uns , den Unterschied zwischen den beiden Typen machen
    • endElement () wird aufgerufen, wenn die Analyse für ein Element endet. In diesem Fall weisen wir den Inhalt der Tags den jeweiligen Variablen zu

Nachdem alle Rückrufe definiert wurden, können wir jetzt die BaeldungHandler- Klasse schreiben :

public class BaeldungHandler extends DefaultHandler { private static final String ARTICLES = "articles"; private static final String ARTICLE = "article"; private static final String TITLE = "title"; private static final String CONTENT = "content"; private Baeldung website; private String elementValue; @Override public void characters(char[] ch, int start, int length) throws SAXException { elementValue = new String(ch, start, length); } @Override public void startDocument() throws SAXException { website = new Baeldung(); } @Override public void startElement(String uri, String lName, String qName, Attributes attr) throws SAXException { switch (qName) { case ARTICLES: website.articleList = new ArrayList(); break; case ARTICLE: website.articleList.add(new BaeldungArticle()); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { switch (qName) { case TITLE: latestArticle().title = elementValue; break; case CONTENT: latestArticle().content = elementValue; break; } } private BaeldungArticle latestArticle() { List articleList = website.articleList; int latestArticleIndex = articleList.size() - 1; return articleList.get(latestArticleIndex); } public Baeldung getWebsite() { return website; } } 

String-Konstanten wurden ebenfalls hinzugefügt, um die Lesbarkeit zu verbessern. Eine Methode zum Abrufen des zuletzt gefundenen Artikels ist ebenfalls praktisch. Schließlich brauchen wir einen Getter für das Baeldung- Objekt.

Beachten Sie, dass das oben Gesagte nicht threadsicher ist, da wir den Status zwischen den Methodenaufrufen beibehalten.

6. Testen des Parsers

Um den Parser zu testen, werden wir die SaxFactory , den SaxParser und auch den BaeldungHandler instanziieren :

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

Danach analysieren wir die XML-Datei und stellen fest, dass das Objekt alle erwarteten Elemente enthält, die analysiert wurden:

saxParser.parse("src/test/resources/sax/baeldung.xml", baeldungHandler); SaxParserMain.Baeldung result = baeldungHandler.getWebsite(); assertNotNull(result); List articles = result.getArticleList(); assertNotNull(articles); assertEquals(3, articles.size()); SaxParserMain.BaeldungArticle articleOne = articles.get(0); assertEquals("Parsing an XML File Using SAX Parser", articleOne.getTitle()); assertEquals("SAX Parser's Lorem ipsum...", articleOne.getContent()); SaxParserMain.BaeldungArticle articleTwo = articles.get(1); assertEquals("Parsing an XML File Using DOM Parser", articleTwo.getTitle()); assertEquals("DOM Parser's Lorem ipsum...", articleTwo.getContent()); SaxParserMain.BaeldungArticle articleThree = articles.get(2); assertEquals("Parsing an XML File Using StAX Parser", articleThree.getTitle()); assertEquals("StAX Parser's Lorem ipsum...", articleThree.getContent()); 

Wie erwartet wurde die Baeldung korrekt analysiert und enthält die erwarteten Unterobjekte .

7. Fazit

Wir haben gerade herausgefunden, wie man mit SAX XML-Dateien analysiert. Es ist eine leistungsstarke API, die in unseren Anwendungen einen geringen Speicherbedarf erzeugt.

Wie üblich ist der Code für diesen Artikel auf GitHub verfügbar.