Pemrosesan dokumen XML di Java menggunakan XPath dan XSLT

Extensible Markup Language (XML) tentu saja merupakan salah satu teknologi terpanas saat ini. Meskipun konsep bahasa markup bukanlah hal baru, XML tampaknya sangat menarik bagi programmer Java dan Internet. Java API for XML Parsing (JAXP; lihat Sumber), yang baru-baru ini didefinisikan melalui Proses Komunitas Java, berjanji untuk menyediakan antarmuka umum untuk mengakses dokumen XML. W3C telah mendefinisikan apa yang disebut Model Objek Dokumen (DOM), yang menyediakan antarmuka standar untuk bekerja dengan dokumen XML dalam hierarki pohon, sedangkan API Sederhana untuk XML (SAX) memungkinkan program mengurai dokumen XML secara berurutan, berdasarkan pada model penanganan acara. Kedua standar ini (SAX menjadi standar de facto) melengkapi JAXP. Bersama-sama, ketiga API ini memberikan dukungan yang cukup untuk menangani dokumen XML di Java,dan banyak buku di pasaran menjelaskan penggunaannya.

Artikel ini memperkenalkan cara untuk menangani dokumen XML yang melampaui API Java standar untuk memanipulasi XML. Kita akan melihat bahwa dalam banyak kasus XPath dan XSLT menyediakan cara yang lebih sederhana dan lebih elegan untuk menyelesaikan masalah aplikasi. Dalam beberapa contoh sederhana, kami akan membandingkan solusi Java / XML murni dengan solusi yang menggunakan XPath dan / atau XSLT.

Baik XSLT dan XPath adalah bagian dari spesifikasi Extensible Stylesheet Language (XSL) (lihat Sumberdaya). XSL terdiri dari tiga bagian: spesifikasi bahasa XSL itu sendiri, Transformasi XSL (XSLT), dan XML Path Language (XPath). XSL adalah bahasa untuk mengubah dokumen XML; ini mencakup definisi - Memformat Objek - tentang bagaimana dokumen XML dapat diformat untuk presentasi. XSLT menetapkan kosakata untuk mengubah satu dokumen XML menjadi dokumen lain. Anda dapat menganggap XSLT sebagai XSL dikurangi Objek Pemformatan. Bahasa XPath membahas bagian tertentu dari dokumen XML dan dimaksudkan untuk digunakan dari dalam lembar gaya XSLT.

Untuk keperluan artikel ini, diasumsikan bahwa Anda sudah familiar dengan dasar-dasar XML dan XSLT, serta DOM API. (Untuk informasi dan tutorial tentang topik ini, lihat Sumberdaya.)

Catatan: Contoh kode artikel ini dikompilasi dan diuji dengan parser XML Apache Xerces dan prosesor Apache Xalan XSL (lihat Sumberdaya).

Masalah

Banyak artikel dan makalah yang berhubungan dengan XML menyatakan bahwa ini adalah sarana yang sempurna untuk mencapai praktik desain yang baik dalam pemrograman Web: pola Model-View-Controller (MVC), atau, dalam istilah yang lebih sederhana, pemisahan data aplikasi dari data presentasi . Jika data aplikasi diformat dalam XML, itu dapat dengan mudah diikat - biasanya dalam servlet atau Java ServerPage - ke, katakanlah, templat HTML dengan menggunakan lembar gaya XSL.

Namun XML dapat melakukan lebih dari sekadar membantu pemisahan tampilan model untuk frontend aplikasi. Saat ini kami mengamati semakin meluasnya penggunaan komponen (misalnya, komponen yang dikembangkan menggunakan standar EJB) yang dapat digunakan untuk merakit aplikasi, sehingga meningkatkan produktivitas pengembang. Usabilitas komponen dapat ditingkatkan dengan memformat data yang ditangani komponen dengan cara standar. Memang, kita bisa berharap untuk melihat lebih banyak lagi komponen yang diterbitkan yang menggunakan XML untuk menggambarkan antarmukanya.

Karena data berformat XML adalah bahasa-netral, itu menjadi dapat digunakan dalam kasus di mana klien dari layanan aplikasi tertentu tidak dikenal, atau ketika tidak boleh memiliki ketergantungan pada server. Misalnya, dalam lingkungan B2B, mungkin tidak dapat diterima bagi dua pihak untuk memiliki ketergantungan pada antarmuka objek Java yang konkret untuk pertukaran data mereka. Teknologi baru seperti Simple Object Access Protocol (SOAP) (lihat Sumber) menangani persyaratan ini.

Semua kasus ini memiliki satu kesamaan: data disimpan dalam dokumen XML dan perlu dimanipulasi oleh aplikasi. Misalnya, aplikasi yang menggunakan berbagai komponen dari vendor yang berbeda kemungkinan besar harus mengubah struktur data (XML) agar sesuai dengan kebutuhan aplikasi atau mematuhi standar tertentu.

Kode yang ditulis menggunakan Java API yang disebutkan di atas pasti akan melakukan ini. Selain itu, semakin banyak alat yang tersedia yang dapat Anda gunakan untuk mengubah dokumen XML menjadi JavaBean dan sebaliknya, yang membuatnya lebih mudah untuk menangani data dari dalam program Java. Namun, dalam banyak kasus, aplikasi, atau setidaknya sebagian darinya, hanya memproses satu atau lebih dokumen XML sebagai masukan dan mengubahnya menjadi format XML yang berbeda sebagai keluaran. Menggunakan stylesheet dalam kasus tersebut adalah alternatif yang layak, seperti yang akan kita lihat nanti di artikel ini.

Gunakan XPath untuk menemukan node dalam dokumen XML

Seperti yang dinyatakan di atas, bahasa XPath digunakan untuk menemukan bagian tertentu dari dokumen XML. Dengan demikian, ini dimaksudkan untuk digunakan oleh lembar gaya XSLT, tetapi tidak ada yang menghalangi kami untuk menggunakannya dalam program Java kami untuk menghindari iterasi yang berkepanjangan atas hierarki elemen DOM. Memang, kami dapat membiarkan prosesor XSLT / XPath bekerja untuk kami. Mari kita lihat cara kerjanya.

Mari kita asumsikan bahwa kita memiliki skenario aplikasi di mana dokumen XML sumber disajikan kepada pengguna (mungkin setelah diproses oleh stylesheet). Pengguna membuat pembaruan pada data dan, untuk menghemat bandwidth jaringan, hanya mengirim rekaman yang diperbarui kembali ke aplikasi. Aplikasi mencari fragmen XML dalam dokumen sumber yang perlu diperbarui dan menggantinya dengan data baru.

Kami akan membuat sedikit sampel yang akan membantu Anda memahami berbagai opsi. Untuk contoh ini, kami berasumsi bahwa aplikasi berurusan dengan catatan alamat di file addressbook. Contoh addressbookdokumen terlihat seperti ini:

  John Smith 250 18th Ave SE Rochester MN 55902 Bill Morris 1234 Jalur Tengah NW St. Paul MN 55123   

Aplikasi (mungkin, meskipun tidak harus, servlet) menyimpan sebuah instance dari addressbookdalam memori sebagai Documentobjek DOM . Saat pengguna mengubah alamat, bagian depan aplikasi hanya mengirimkan elemen yang diperbarui .

The elemen digunakan untuk secara unik mengidentifikasi sebuah alamat; itu berfungsi sebagai kunci utama. Ini tidak masuk akal untuk aplikasi nyata, tetapi kami melakukannya di sini untuk menjaga agar semuanya tetap sederhana.

Kami sekarang perlu menulis beberapa kode Java yang akan membantu kami mengidentifikasi elemen di pohon sumber yang perlu diganti dengan elemen yang diperbarui. The findAddress()metode di bawah ini menunjukkan bagaimana yang dapat dicapai. Harap perhatikan bahwa, agar sampel tetap singkat, kami meninggalkan penanganan kesalahan yang sesuai.

public Node findAddress (Nama string, Sumber dokumen) {Elemen root = source.getDocumentElement (); NodeList nl = root.getChildNodes (); // iterasi ke semua node alamat dan temukan yang memiliki alamat yang benar untuk (int i = 0; i
   
    

Kode di atas kemungkinan besar dapat dioptimalkan, tetapi jelas bahwa pengulangan pada pohon DOM bisa membosankan dan rawan kesalahan. Sekarang mari kita lihat bagaimana node target dapat ditemukan dengan menggunakan pernyataan XPath sederhana. Pernyataannya bisa seperti ini:

// alamat [child :: addressee [text () = 'Jim Smith']] 

Sekarang kita dapat menulis ulang metode sebelumnya. Kali ini, kami menggunakan pernyataan XPath untuk menemukan node yang diinginkan:

public Node findAddress (Nama string, Sumber dokumen) melempar Exception {// perlu membuat ulang beberapa objek pembantu XMLParserLiaison xpathSupport = new XMLParserLiaisonDefault (); XPathProcessor xpathParser = XPathProcessorImpl baru (xpathSupport); PrefixResolver prefixResolver = new PrefixResolverDefault (source.getDocumentElement ()); // buat XPath dan inisialisasi XPath xp = new XPath (); String xpString = "// alamat [anak :: addressee [text () = '" + nama + "']]"; xpathParser.initXPath (xp, xpString, prefixResolver); // sekarang jalankan pernyataan pilih XPath daftar XObject = xp.execute (xpathSupport, source.getDocumentElement (), prefixResolver); // kembalikan node yang dihasilkan list.nodeset (). item (0); }

Kode di atas mungkin tidak terlihat jauh lebih baik dari percobaan sebelumnya, tetapi sebagian besar konten metode ini dapat dienkapsulasi dalam kelas helper. Satu-satunya bagian yang berubah terus menerus adalah ekspresi XPath yang sebenarnya dan node target.

Ini memungkinkan kita membuat XPathHelperkelas, yang terlihat seperti ini:

import org.w3c.dom.*; import org.xml.sax.*; import org.apache.xalan.xpath.*; import org.apache.xalan.xpath.xml.*; public class XPathHelper { XMLParserLiaison xpathSupport = null; XPathProcessor xpathParser = null; PrefixResolver prefixResolver = null; XPathHelper() { xpathSupport = new XMLParserLiaisonDefault(); xpathParser = new XPathProcessorImpl(xpathSupport); } public NodeList processXPath(String xpath, Node target) thrws SAXException { prefixResolver = new PrefixResolverDefault(target); // create the XPath and initialize it XPath xp = new XPath(); xpathParser.initXPath(xp, xpath, prefixResolver); // now execute the XPath select statement XObject list = xp.execute(xpathSupport, target, prefixResolver); // return the resulting node return list.nodeset(); } } 

After creating the helper class, we can rewrite our finder method again, which is now very short:

public Node findAddress(String name, Document source) throws Exception { XPathHelper xpathHelper = new XPathHelper(); NodeList nl = xpathHelper.processXPath( "//address[child::addressee[text() = '"+name+"']]", source.getDocumentElement()); return nl.item(0); } 

The helper class can now be used whenever a node or a set of nodes needs to be located in a given XML document. The actual XPath statement could even be loaded from an external source, so that changes could be made on the fly if the source document structure changes. In this case, no recompile is necessary.

Process XML documents with XSL stylesheets

In some cases, it makes sense to outsource the entire handling of an XML document to an external XSL stylesheet, a process in some respects similar to the use of XPath as described in the previous section. With XSL stylesheets, you can create an output document by selecting nodes from the input document and merging their content with stylesheet content, based on pattern rules.

If an application changes the structure and content of an XML document and producing a new document, it may be better and easier to use a stylesheet to handle the work rather than writing a Java program that does the same job. The stylesheet is most likely stored in an external file, allowing you to change it on the fly, without the need to recompile.

Misalnya, kita dapat menyelesaikan pemrosesan addressbooksampel dengan membuat lembar gaya yang menggabungkan versi cache dengan versi addressbookyang diperbarui, sehingga membuat dokumen baru dengan pembaruan di dalamnya.

Berikut adalah contoh lembar gaya seperti itu:

   //mymachine.com/changed.xml