Sokongan Perpustakaan XML di Java

1. Pengenalan

Dalam artikel ini kita akan membandingkan perpustakaan dan API Java XML.

Ini adalah artikel kedua dari seri tentang dukungan Java untuk XML, jika Anda ingin mendalami lebih lanjut mengenai sokongan XPath di Java, lihat artikel sebelumnya.

2. Gambaran keseluruhan

Sekarang kita akan menggali lebih mendalam mengenai sokongan dunia XML dan untuk itu kita akan memulakan dengan menjelaskan sesederhana mungkin semua inisial yang berkaitan dengan subjek.

Dalam sokongan Java XML kami dapat menemukan beberapa definisi API, masing-masing mempunyai kelebihan dan kekurangan

SAX : Ini adalah parsing API berdasarkan acara, menyediakan akses tahap rendah, efisien memori dan lebih cepat daripada DOM kerana ia tidak memuatkan keseluruhan pohon dokumen dalam memori tetapi tidak memberikan sokongan untuk navigasi seperti yang disediakan oleh XPath, walaupun lebih cekap, lebih sukar untuk digunakan juga.

DOM : Ia sebagai penghurai berdasarkan model yang memuatkan dokumen struktur pohon dalam memori, jadi kami mempunyai susunan elemen aslinya, kami dapat menavigasi dokumen kami ke kedua arah, ia menyediakan API untuk membaca dan menulis, ia menawarkan manipulasi XML dan sangat senang digunakan walaupun harganya tinggi pada sumber memori.

StAX : Ia menawarkan kemudahan DOM dan kecekapan SAX tetapi kekurangan beberapa fungsi yang disediakan oleh DOM seperti manipulasi XML dan ia hanya membolehkan kita menavigasi dokumen ke hadapan.

JAXB : Ia membolehkan kita menavigasi dokumen ke dua arah, lebih efisien daripada DOM, membenarkan penukaran dari XML ke jenis java dan menyokong manipulasi XML tetapi hanya dapat menguraikan dokumen XML yang sah.

Anda masih dapat mencari sebilangan rujukan untuk JAXP tetapi keluaran terakhir projek ini adalah dari bulan Mac 2013 dan hampir mati.

Jadual API XML

3. XML

Di bahagian ini kita akan melihat pelaksanaan yang paling popular, sehingga kita dapat menguji sampel kerja yang sebenarnya dan memeriksa perbezaan di antara mereka.

Dalam contoh berikut, kami akan menggunakan fail XML sederhana dengan struktur seperti ini:

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

4. DOM4J

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

Ini adalah salah satu perpustakaan yang paling popular untuk digunakan dengan fail XML , kerana ia membolehkan kita melakukan pembacaan dua arah, membuat dokumen baru dan mengemas kini yang sedia ada.

DOM4J boleh berfungsi dengan DOM , SAX , XPath dan XLST . SAX disokong melalui JAXP .

Mari kita lihat di sini sebagai contoh, bagaimana kita boleh memilih penapisan elemen mengikut id yang diberikan.

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

The SAXReader kelas adalah bertanggungjawab mewujudkan DOM4J pokok dari SAX acara parsing. Sebaik sahaja kita mempunyai dokumen org.dom4j.Doc kita hanya perlu memanggil kaedah yang diperlukan dan menyampaikannya sebagai ungkapan XPath sebagai Rentetan.

Kami dapat memuatkan dokumen yang ada, membuat perubahan pada kandungannya dan kemudian mengemas kini fail asalnya.

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

Dalam contoh di atas, kami mengubah setiap kandungan tajuk dan membuat fail baru.

Perhatikan di sini betapa mudahnya memasukkan setiap simpul tajuk dalam senarai dengan memanggil elementIterator dan meneruskan nama nod.

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

Membuat dokumen baru dari awal semudah 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 kami koleksi kaedah untuk digunakan oleh DOM4J , seperti createDocument yang membuat dokumen kosong untuk mulai bekerja dengannya.

Kita dapat membuat seberapa banyak atribut atau elemen yang kita perlukan dengan kaedah yang disediakan oleh DOM4J , dan setelah dokumen kita selesai, kita hanya menulisnya ke fail seperti yang kita lakukan dengan kes kemas kini sebelumnya.

5. JDOM

Untuk bekerjasama dengan JDOM, kita harus menambahkan kebergantungan ini ke pom kita.

Gaya kerja JDOM hampir sama dengan gaya DOM4J , jadi kita akan melihat 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 akar dengan cara yang sangat mudah seperti yang dapat kita 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 dalam kod di atas, kita mempunyai SAXBuilder membuat contoh Dokumen dari fail tertentu. Kami mengambil elemen dengan atribut tutId dengan menyampaikan 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.