Unterstützung für XML-Bibliotheken in Java

1. Einleitung

In diesem Artikel werden wir Java XML-Bibliotheken und APIs vergleichen.

Dies ist der zweite Artikel aus der Reihe über die Java-Unterstützung für XML. Wenn Sie tiefer in die XPath-Unterstützung in Java einsteigen möchten, lesen Sie den vorherigen Artikel.

2. Übersicht

Jetzt werden wir uns eingehender mit der Unterstützung der XML-Welt befassen und zunächst alle themenbezogenen Initialen so einfach wie möglich erklären.

In der Java XML-Unterstützung finden wir nur wenige API-Definitionen, von denen jede ihre Vor- und Nachteile hat.

SAX : Es handelt sich um eine ereignisbasierte Analyse-API, die einen Zugriff auf niedriger Ebene bietet, speichereffizient und schneller als DOM ist, da nicht der gesamte Dokumentbaum in den Speicher geladen wird, jedoch keine Navigation wie die bereitgestellte unterstützt wird von XPath, obwohl es effizienter ist, ist es auch schwieriger zu verwenden.

DOM : Es ist ein modellbasierter Parser, der ein Baumstrukturdokument in den Speicher lädt, sodass wir die ursprüngliche Elementreihenfolge haben. Wir können unser Dokument in beide Richtungen navigieren. Es bietet eine API zum Lesen und Schreiben. Es bietet XML-Manipulation und es ist sehr einfach zu bedienen, obwohl der Preis die Speicherressourcen stark belastet.

StAX : Es bietet die Einfachheit von DOM und die Effizienz von SAX, es fehlen jedoch einige von DOM bereitgestellte Funktionen wie die XML-Manipulation, und es ermöglicht uns nur, das Dokument vorwärts zu navigieren.

JAXB : Es ermöglicht uns, durch das Dokument in beide Richtungen zu navigieren, ist effizienter als DOM, ermöglicht die Konvertierung von XML in Java-Typen und unterstützt die XML-Manipulation, kann jedoch nur ein gültiges XML-Dokument analysieren.

Sie konnten noch einige Verweise auf JAXP finden, aber die letzte Veröffentlichung dieses Projekts ist vom März 2013 und es ist praktisch tot.

XML-APIs-Tabelle

3. Das XML

In diesem Abschnitt werden die beliebtesten Implementierungen vorgestellt, damit wir echte Arbeitsproben testen und Unterschiede zwischen ihnen überprüfen können.

In den folgenden Beispielen arbeiten wir mit einer einfachen XML-Datei mit einer Struktur wie dieser:

  Guava Introduction to Guava 04/04/2016 GuavaAuthor  ... 

4. DOM4J

Zunächst werfen wir einen Blick darauf, was wir mit DOM4J tun können. In diesem Beispiel müssen wir die letzte Version dieser Abhängigkeit hinzufügen.

Dies ist eine der beliebtesten Bibliotheken für die Arbeit mit XML- Dateien, da wir damit bidirektional lesen, neue Dokumente erstellen und vorhandene aktualisieren können.

DOM4J kann mit DOM , SAX , XPath und XLST arbeiten . SAX wird über JAXP unterstützt .

Schauen wir uns hier zum Beispiel an, wie wir eine Elementfilterung nach einer bestimmten ID auswählen können.

SAXReader reader = new SAXReader(); Document document = reader.read(file); List elements = document.selectNodes("//*[@tutId='" + id + "']"); return elements.get(0);

Die SAXReader- Klasse ist für die Erstellung eines DOM4J- Baums aus SAX- Analyseereignissen verantwortlich . Sobald wir ein org.dom4j.Document haben, müssen wir nur die erforderliche Methode aufrufen und den XPath- Ausdruck als String an ihn übergeben.

Wir können ein vorhandenes Dokument laden, Änderungen am Inhalt vornehmen und dann die Originaldatei aktualisieren.

for (Node node : nodes) { Element element = (Element)node; Iterator iterator = element.elementIterator("title"); while (iterator.hasNext()) { Element title =(Element)iterator.next(); title.setText(title.getText() + " updated"); } } XMLWriter writer = new XMLWriter( new FileWriter(new File("src/test/resources/example_updated.xml"))); writer.write(document); writer.close();

Im obigen Beispiel ändern wir den Inhalt jedes Titels und erstellen eine neue Datei.

Beachten Sie hier, wie einfach es ist, den Knoten jedes Titels in einer Liste abzurufen, indem Sie elementIterator aufrufen und den Namen des Knotens übergeben.

Sobald wir unseren Inhalt geändert haben, verwenden wir den XMLWriter , der einen DOM4J- Baum nimmt und ihn als XML in einen Stream formatiert .

Das Erstellen eines neuen Dokuments von Grund auf ist so einfach wie unten dargestellt.

Document document = DocumentHelper.createDocument(); Element root = document.addElement("XMLTutorials"); Element tutorialElement = root.addElement("tutorial").addAttribute("tutId", "01"); tutorialElement.addAttribute("type", "xml"); tutorialElement.addElement("title").addText("XML with Dom4J"); ... OutputFormat format = OutputFormat.createPrettyPrint(); XMLWriter writer = new XMLWriter( new FileWriter(new File("src/test/resources/example_new.xml")), format); writer.write(document); writer.close(); 

DocumentHelper bietet eine Sammlung von Methoden, die von DOM4J verwendet werden können , z. B. createDocument , mit dem ein leeres Dokument erstellt wird, um mit der Arbeit zu beginnen.

Mit den von DOM4J bereitgestellten Methoden können wir so viele Attribute oder Elemente erstellen, wie wir benötigen. Sobald wir unser Dokument fertiggestellt haben, schreiben wir es einfach in eine Datei, wie wir es zuvor mit dem Aktualisierungsfall getan haben.

5. JDOM

Um mit JDOM arbeiten zu können, müssen wir diese Abhängigkeit zu unserem POM hinzufügen.

Der Arbeitsstil von JDOM ist dem von DOM4J ziemlich ähnlich , daher werden wir uns nur einige Beispiele ansehen:

SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(this.getFile()); Element tutorials = doc.getRootElement(); List titles = tutorials.getChildren("tutorial"); 

Im obigen Beispiel rufen wir alle Elemente auf sehr einfache Weise aus dem Stammelement ab , wie wir es mit DOM4J tun können:

SAXBuilder builder = new SAXBuilder(); Document document = (Document) builder.build(file); String filter = "//*[@tutId='" + id + "']"; XPathFactory xFactory = XPathFactory.instance(); XPathExpression expr = xFactory.compile(filter, Filters.element()); List node = expr.evaluate(document);

Auch hier im obigen Code haben wir einen SAXBuilder , der eine Dokumentinstanz aus einer bestimmten Datei erstellt. Wir rufen ein Element anhand seines tutId- Attributs ab, indem wir einen XPath- Ausdruck an die von JDOM2 bereitgestellte XPathFactory übergeben.

6. STAX

Now, we are going to see how we could retrieve all elements from our root element using the Stax API. Stax is included in the JDK since Java 6 so you don't need to add any dependencies.

Firstly, we need to create a Tutorial class:

public class Tutorial { private String tutId; private String type; private String title; private String description; private String date; private String author; // standard getters and setters }

and then we are ready to follow with:

List tutorials = new ArrayList(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(this.getFile())); Tutorial current; while (eventReader.hasNext()) { XMLEvent event = eventReader.nextEvent(); switch (event.getEventType()) { case XMLStreamConstants.START_ELEMENT: StartElement startElement = event.asStartElement(); String qName = startElement.getName().getLocalPart(); ... break; case XMLStreamConstants.CHARACTERS: Characters characters = event.asCharacters(); ... break; case XMLStreamConstants.END_ELEMENT: EndElement endElement = event.asEndElement(); // check if we found the closing element // close resources that need to be explicitly closed break; } }

In the example above, in order to help us retrieve the information, we needed to create a class to store the retrieved data in.

To read the document, we declared what is called event handlers and we used them to navigate our document ahead. Remember that the SAX implementations don't provide bi-directional navigation. As you can see here, a lot of work needs to be done just to retrieve a simple list of elements.

7. JAXB

JAXB is included with the JDK, as well as Xerces, se don't need any extra dependency for this one.

It's very simple to load, create and manipulate information from an XML file using JAXB.

We just need to create the correct java entities to bind the XML and that's it.

JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); Tutorials tutorials = (Tutorials) jaxbUnmarshaller.unmarshal(this.getFile());

In the example above, we load our XML file into our object and from there we can handle everything as a normal Java structure;

To create a new document, it is as simple as reading it but doing the reverse way, like done in the below code.

Firstly, we are going to modify our Tutorial class to add JAXB annotations to getters and setters:

public class Tutorial { ... public String getTutId() { return tutId; } @XmlAttribute public void setTutId(String tutId) { this.tutId = tutId; } ... @XmlElement public void setTitle(String title) { this.title = title; } ... } @XmlRootElement public class Tutorials { private List tutorial; // standard getters and setters with @XmlElement annotation }

With @XmlRootElement we define what object is going to represent the root node of our document and then we use @XmlAttribute or @XmlElement to define whether that attribute represents an attribute of a node or an element of the document.

Then we can follow with:

Tutorials tutorials = new Tutorials(); tutorials.setTutorial(new ArrayList()); Tutorial tut = new Tutorial(); tut.setTutId("01"); ... tutorials.getTutorial().add(tut); JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(tutorials, file);

As you can see, binding XML file to Java objects is the easiest way to work this kind of files.

8. XPath Expression Support

To create complex XPath expressions, we can use Jaxen. This is an open source XPath library adaptable to many different object models, including DOM, XOM, DOM4J, and JDOM.

We can create XPath expressions and compile them against many supported documents.

String expression = "/tutorials/tutorial"; XPath path = new DOMXPath(expression); List result = path.selectNodes(xmlDocument);

To make it work we'll need to add this dependency to our project.

9. Conclusion

As you can see there are many options for working with XML, depending on the requirements of your application, you could work with any of them or you may have to choose between efficiency and simplicity.

You can find the full working samples for this article in our git repository here.