Saya selalu menemukan XML agak rumit untuk diproses. Saya tidak berbicara tentang menerapkan parser XML: Saya berbicara tentang menggunakan parser berbasis aliran yang ada, seperti parser SAX, yang memproses XML node demi node.
Ya, sangat mudah untuk mempelajari berbagai API untuk parser ini, tetapi setiap kali saya melihat kode yang memproses XML saya selalu merasa agak berbelit-belit. Masalah mendasar tampaknya adalah bahwa dokumen XML secara logis dipisahkan menjadi node individual, namun tipe data dan atributnya sering dipisahkan dari data aktual, kadang-kadang oleh beberapa tingkat sarang. Oleh karena itu, ketika memproses node tertentu secara individual, banyak kondisi tambahan perlu dipertahankan untuk menentukan di mana kita berada dan apa yang perlu kita lakukan selanjutnya.
Misalnya, diberi potongan dari dokumen XML khas:
<book>
<title>Blah blah</title>
<author>Blah blah</author>
<price>15 USD</price>
</book>
... Bagaimana saya menentukan kapan saya menemukan simpul teks yang berisi judul buku? Misalkan kita memiliki parser XML sederhana yang bertindak seperti iterator, memberi kita simpul berikutnya dalam dokumen XML setiap kali kita memanggil XMLParser.getNextNode()
. Saya pasti menemukan diri saya menulis kode seperti berikut:
boolean insideBookNode = false;
boolean insideTitleNode = false;
while (!XMLParser.finished())
{
....
XMLNode n = XMLParser.getNextNode();
if (n.type() == XMLTextNode)
{
if (insideBookNode && insideTitleNode)
{
// We have a book title, so do something with it
}
}
else
{
if (n.type() == XMLStartTag)
{
if (n.name().equals("book")) insideBookNode = true
else if (n.name().equals("title")) insideTitleNode = true;
}
else if (n.type() == XMLEndTag)
{
if (n.name().equals("book")) insideBookNode = false;
else if (n.name().equals("title")) insideTitleNode = false;
}
}
}
Pada dasarnya, pemrosesan XML dengan cepat berubah menjadi loop besar yang digerakkan oleh mesin negara, dengan banyak variabel status yang digunakan untuk menunjukkan node induk yang kami temukan sebelumnya. Jika tidak, objek tumpukan harus dipertahankan untuk melacak semua tag yang disarangkan. Ini dengan cepat menjadi rawan kesalahan dan sulit untuk dipertahankan.
Sekali lagi, masalahnya adalah bahwa data yang kami minati tidak terkait langsung dengan satu node. Tentu, bisa jadi, jika kita menulis XML seperti:
<book title="Blah blah" author="blah blah" price="15 USD" />
... tapi ini jarang bagaimana XML digunakan dalam kenyataan. Sebagian besar kita memiliki simpul teks sebagai anak-anak dari simpul induk, dan kita perlu melacak simpul induk untuk menentukan apa yang dimaksud dengan simpul teks.
Jadi ... apakah saya melakukan sesuatu yang salah? Apakah ada cara yang lebih baik? Pada titik apakah menggunakan parser berbasis aliran XML menjadi terlalu rumit, sehingga parser DOM yang lengkap menjadi perlu? Saya ingin mendengar dari programmer lain idiom apa yang mereka gunakan saat memproses XML dengan parser berbasis aliran. Haruskah parsing XML berbasis aliran selalu berubah menjadi mesin negara yang besar?
sumber
Jawaban:
Bagi saya, pertanyaannya adalah sebaliknya. Pada titik apa Dokumen XML menjadi begitu rumit, sehingga Anda harus mulai menggunakan SAX daripada DOM?
Saya hanya akan menggunakan SAX untuk aliran data yang sangat besar dan berukuran tak tentu; atau jika perilaku yang ingin dipanggil oleh XML benar-benar didorong oleh peristiwa, dan karena itu mirip SAX.
Contoh yang Anda berikan terlihat sangat mirip DOM bagi saya.
EDIT: Saya juga menggunakan SAX untuk stream yang mungkin cacat, tetapi di mana saya ingin membuat perkiraan terbaik untuk mendapatkan data.
sumber
Saya tidak bekerja dengan XML terlalu banyak, sedikit menurut saya, mungkin salah satu cara terbaik untuk mem-parsing XML dengan perpustakaan menggunakan XPath.
Alih-alih melintasi pohon untuk menemukan beberapa node tertentu, Anda memberikan path ke sana. Dalam hal contoh Anda (dalam pseudocode), itu akan menjadi seperti:
XPath jauh lebih kuat dari itu, Anda dapat mencari menggunakan kondisi (baik pada nilai dan atribut), pilih node tertentu dalam daftar, pindahkan level melalui pohon. Saya sarankan Anda mencari info tentang cara menggunakannya, ini diterapkan di banyak parsing libraries (saya menggunakannya versi .Net Framework dan lxml untuk Python)
sumber
Biasanya begitu, ya.
Bagi saya untuk menunjukkan menggunakan parser DOM yang lengkap adalah ketika saya perlu meniru bagian-bagian dari hirarki file dalam memori, misalnya untuk dapat menyelesaikan referensi silang dalam dokumen.
sumber
Parsing secara umum hanya mengendarai mesin negara, dan parsing XML tidak berbeda. Parsing berbasis aliran selalu merepotkan, saya selalu berakhir dengan membangun semacam tumpukan untuk melacak node leluhur, dan mendefinisikan banyak acara dan semacam dispatcher acara yang memeriksa tag atau lintasan registri dan menyalakan suatu acara jika ada yang cocok. Kode inti cukup ketat, tetapi saya berakhir dengan sejumlah besar penangan acara yang sebagian besar terdiri dari menetapkan nilai simpul teks berikut ke bidang dalam struktur di suatu tempat. Ini bisa menjadi sangat berbulu jika Anda perlu mencampur logika bisnis di sana juga.
Saya akan selalu menggunakan DOM kecuali masalah ukuran atau kinerja mendikte sebaliknya.
sumber
Tidak sepenuhnya agnostik bahasa, tapi saya biasanya membatalkan XML ke dalam objek daripada memikirkan parsing. Hanya waktu untuk khawatir tentang strategi penguraian per se adalah jika Anda memiliki masalah kecepatan.
sumber
Menjadi jauh lebih rumit jika Anda dapat menggunakan XPath. Dan dalam .Net LINQ ke XML abstrak banyak hal yang kurang glamor juga. ( Edit - ini tentu saja memerlukan pendekatan DOM)
Pada dasarnya, jika Anda mengambil pendekatan berbasis aliran (sehingga Anda tidak dapat menggunakan abstraksi yang lebih baik yang memerlukan DOM) Saya pikir itu akan selalu sangat rumit dan saya tidak yakin ada cara untuk mengatasi ini.
sumber
Jika Anda dapat menemukan parser yang memberi Anda iterator, pernahkah Anda menganggapnya sebagai lexer, dan menggunakan generator mesin negara?
sumber