Dukungan Perpustakaan XML di Java

1. Perkenalan

Pada artikel ini kita akan membandingkan pustaka XML dan API Java.

Ini adalah artikel kedua dari seri tentang dukungan Java untuk XML, jika Anda ingin mempelajari lebih dalam tentang dukungan XPath di Java, lihat artikel sebelumnya.

2. Ikhtisar

Sekarang kita akan menggali lebih dalam tentang dukungan dunia XML dan untuk itu kita akan mulai dengan menjelaskan sesederhana mungkin semua inisial yang berhubungan dengan subjek.

Dalam dukungan Java XML kita dapat menemukan beberapa definisi API, masing-masing memiliki pro dan kontra.

SAX : Ini adalah API penguraian berbasis peristiwa, yang menyediakan akses tingkat rendah, hemat memori, dan lebih cepat daripada DOM karena tidak memuat seluruh pohon dokumen dalam memori tetapi tidak memberikan dukungan untuk navigasi seperti yang disediakan oleh XPath, meskipun lebih efisien, lebih sulit untuk digunakan juga.

DOM : Ini sebagai parser berbasis model yang memuat dokumen struktur pohon dalam memori, jadi kami memiliki urutan elemen asli, kami dapat menavigasi dokumen kami ke dua arah, menyediakan API untuk membaca dan menulis, menawarkan manipulasi XML dan sangat mudah digunakan meskipun harganya sangat membebani sumber daya memori.

StAX : Menawarkan kemudahan DOM dan efisiensi SAX tetapi tidak memiliki beberapa fungsi yang disediakan oleh DOM seperti manipulasi XML dan hanya memungkinkan kita untuk mengarahkan dokumen ke depan.

JAXB : Ini memungkinkan kita untuk menavigasi dokumen di kedua arah, ini lebih efisien daripada DOM, memungkinkan konversi dari XML ke tipe java dan mendukung manipulasi XML tetapi hanya dapat mengurai dokumen XML yang valid.

Anda masih dapat menemukan beberapa referensi ke JAXP tetapi rilis terakhir dari proyek ini adalah dari Maret 2013 dan secara praktis sudah mati.

Tabel API XML

3. XML

Di bagian ini kita akan melihat implementasi yang paling populer, sehingga kita dapat menguji sampel kerja nyata dan memeriksa perbedaan di antara mereka.

Dalam contoh berikut kami akan bekerja dengan file XML sederhana dengan struktur seperti ini:

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

4. DOM4J

Kita akan mulai dengan melihat apa yang dapat kita lakukan dengan DOM4J dan untuk contoh ini kita perlu menambahkan versi terakhir dari ketergantungan ini.

Ini adalah salah satu pustaka paling populer untuk bekerja dengan file XML , karena memungkinkan kita untuk melakukan pembacaan dua arah, membuat dokumen baru dan memperbarui yang sudah ada.

DOM4J dapat bekerja dengan DOM , SAX , XPath dan XLST . SAX didukung melalui JAXP .

Mari kita lihat di sini misalnya, bagaimana kita bisa memilih elemen yang memfilter dengan id yang diberikan.

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

Kelas SAXReader bertanggung jawab untuk membuat pohon DOM4J dari peristiwa penguraian SAX . Setelah kita memiliki org.dom4j.Document, kita hanya perlu memanggil metode yang diperlukan dan meneruskan ekspresi XPath sebagai String.

Kami dapat memuat dokumen yang ada, membuat perubahan pada isinya dan kemudian memperbarui file aslinya.

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();

Pada contoh di atas, kami mengubah setiap konten judul dan membuat file baru.

Perhatikan di sini betapa sederhananya mendapatkan setiap node judul dalam daftar dengan memanggil elementIterator dan meneruskan nama node tersebut.

Setelah konten kami dimodifikasi, kami akan menggunakan XMLWriter yang mengambil pohon DOM4J dan memformatnya ke aliran sebagai XML .

Membuat dokumen baru dari awal sesederhana yang kita lihat di bawah.

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 memberi kita sekumpulan metode untuk digunakan oleh DOM4J , seperti createDocument yang membuat dokumen kosong untuk mulai bekerja dengannya.

Kita dapat membuat atribut atau elemen sebanyak yang kita butuhkan dengan metode yang disediakan oleh DOM4J , dan setelah dokumen kita selesai, kita tinggal menulisnya ke file seperti yang kita lakukan dengan kasus pembaruan sebelumnya.

5. JDOM

Untuk bekerja dengan JDOM, kita harus menambahkan ketergantungan ini ke pom kita.

Gaya kerja JDOM sangat mirip dengan DOM4J , jadi kita akan melihat hanya beberapa contoh:

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

Dalam contoh di atas, kami mengambil semua elemen dari elemen root dengan cara yang sangat sederhana seperti yang dapat kami lakukan dengan DOM4J:

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

Sekali lagi, di sini, di kode di atas, kami memiliki SAXBuilder yang membuat instance Dokumen dari file yang diberikan. Kami mengambil elemen dengan atribut tutId -nya dengan meneruskan ekspresi XPath ke XPathFactory yang disediakan oleh JDOM2.

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.