Satu kesalahan yang saya lihat orang membuat berulang - ulang adalah mencoba mem-parsing XML atau HTML dengan regex. Berikut adalah beberapa alasan mengapa parsing XML dan HTML sulit:
Orang ingin memperlakukan file sebagai urutan baris, tetapi ini valid:
<tag
attr="5"
/>
Orang-orang ingin memperlakukan tag <atau <sebagai awal tag, tetapi hal-hal seperti ini ada di alam liar:
<img src="imgtag.gif" alt="<img>" />
Orang-orang sering ingin mencocokkan tag awal dengan tag akhir, tetapi XML dan HTML memungkinkan tag mengandung diri mereka sendiri (yang tidak bisa ditangani oleh regex tradisional sama sekali):
<span id="outer"><span id="inner">foo</span></span>
Orang sering ingin mencocokkan dengan konten dokumen (seperti masalah terkenal "temukan semua nomor telepon pada halaman tertentu"), tetapi data dapat ditandai (bahkan jika itu terlihat normal jika dilihat):
<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>
Komentar mungkin berisi tag yang diformat dengan buruk atau tidak lengkap:
<a href="foo">foo</a>
<!-- FIXME:
<a href="
-->
<a href="bar">bar</a>
Apa saja Gotcha lain yang Anda ketahui?
Jawaban:
Berikut ini beberapa XML valid yang menyenangkan untuk Anda:
Dan kumpulan kecil kesenangan ini adalah HTML yang valid:
Belum lagi semua penguraian khusus browser untuk konstruksi yang tidak valid.
Semoga berhasil mengadu domba regex melawan itu!
EDIT (Jörg W Mittag): Ini adalah bagian lain yang bagus dari HTML 4.01 yang valid dan bagus:
sumber
Sebenarnya
juga bukan HTML yang valid, dan juga bukan XML yang valid.
Ini bukan XML yang valid karena '<' dan '>' bukan karakter yang valid di dalam string atribut. Mereka harus melarikan diri menggunakan entitas XML yang sesuai & lt; dan & gt;
Itu juga bukan HTML yang valid karena formulir penutupan pendek tidak diperbolehkan dalam HTML (tetapi benar dalam XML dan XHTML). Tag 'img' juga merupakan tag tertutup secara implisit sesuai dengan spesifikasi HTML 4.01. Ini berarti bahwa menutupnya secara manual sebenarnya salah, dan setara dengan menutup tag lain dua kali.
Versi yang benar dalam HTML adalah
dan versi yang benar dalam XHTML dan XML adalah
Contoh berikut yang Anda berikan juga tidak valid
Ini juga bukan HTML atau XML yang valid. Nama tag harus tepat di belakang '<', meskipun atribut dan penutupan '>' ada di mana pun mereka inginkan. Jadi XML yang valid sebenarnya
Dan inilah satu lagi yang lebih lucu: Anda sebenarnya dapat memilih untuk menggunakan "atau 'sebagai karakter kutipan atribut Anda
Semua alasan lain yang diposting sudah benar, tetapi masalah terbesar dengan parsing HTML adalah bahwa orang biasanya tidak memahami semua aturan sintaks dengan benar. Fakta bahwa browser Anda mengartikan tagoup Anda sebagai HTML tidak berarti bahwa Anda telah benar-benar menulis HTML yang valid.
Sunting: Dan bahkan stackoverflow.com setuju dengan saya mengenai definisi yang valid dan tidak valid. XML / HTML Anda yang tidak valid tidak disorot, sedangkan versi saya yang diperbaiki adalah.
Pada dasarnya, XML tidak dibuat untuk diuraikan dengan regexps. Tetapi tidak ada alasan untuk melakukannya. Ada banyak, banyak parser XML untuk masing-masing dan setiap bahasa. Anda memiliki pilihan antara parser SAX, parser DOM dan parser Tarik. Semua ini dijamin jauh lebih cepat daripada parsing dengan regexp dan Anda kemudian dapat menggunakan teknologi keren seperti XPath atau XSLT pada pohon DOM yang dihasilkan.
Karenanya, jawaban saya adalah: tidak hanya mem-parsing XML dengan regexps sulit, tetapi juga merupakan ide yang buruk. Cukup gunakan salah satu dari jutaan parser XML yang ada, dan manfaatkan semua fitur canggih XML.
HTML terlalu sulit bahkan untuk mencoba parsing sendiri. Pertama, sintaksis hukum memiliki banyak seluk-beluk kecil yang mungkin tidak Anda sadari, dan kedua, HTML di alam liar hanyalah tumpukan besar yang berbau busuk (Anda mengerti maksud saya). Ada berbagai pustaka lax parser yang melakukan pekerjaan dengan baik dalam menangani HTML seperti sup tag, cukup gunakan ini.
sumber
>
tanda benar-benar berlaku di html stackoverflow.com/questions/94528/...Saya menulis seluruh entri blog tentang hal ini: Batasan Ekspresi Reguler
Inti dari masalah ini adalah bahwa HTML dan XML adalah struktur rekursif yang membutuhkan mekanisme penghitungan agar dapat diurai dengan benar. Regex yang benar tidak dapat menghitung. Anda harus memiliki tata bahasa gratis konteks untuk menghitung.
Paragraf sebelumnya hadir dengan sedikit peringatan. Implementasi regex tertentu sekarang mendukung gagasan rekursi. Namun begitu Anda mulai menambahkan rekursi ke dalam ekspresi regex Anda, Anda benar-benar merentangkan batas dan harus mempertimbangkan parser.
sumber
Satu hal yang tidak ada dalam daftar Anda adalah bahwa atribut dapat muncul dalam urutan apa pun, jadi jika regex Anda mencari tautan dengan href "foo" dan kelas "bar", mereka dapat datang dalam urutan apa pun, dan memiliki sejumlah lainnya hal-hal di antara mereka.
sumber
Itu tergantung pada apa yang Anda maksud dengan "parsing". Secara umum, XML tidak dapat diuraikan menggunakan regex karena tata bahasa XML tidak berarti biasa. Sederhananya, regex tidak bisa menghitung (yah, Perl regex mungkin sebenarnya bisa menghitung hal-hal) sehingga Anda tidak bisa menyeimbangkan tag buka-tutup.
sumber
Apakah orang benar-benar membuat kesalahan dengan menggunakan regex, atau apakah itu cukup baik untuk tugas yang mereka coba capai?
Saya sepenuhnya setuju bahwa parsing html dan xml menggunakan regex tidak dimungkinkan karena orang lain telah menjawab.
Namun, jika kebutuhan Anda bukan untuk mem-parsing html / xml tetapi untuk mendapatkan sedikit data dalam bit "html / xml" yang dikenal baik maka mungkin ekspresi reguler atau bahkan "substring" yang lebih sederhana sudah cukup baik.
sumber
Orang biasanya default untuk menulis pola serakah, cukup sering mengarah ke un-dipikirkan-melalui. * Menyeruput potongan file besar ke dalam <foo>. * </foo> terbesar.
sumber
.*?<
, Anda bisa memperbaikinya dengan menggunakan kelas karakter yang dinegasikan seperti[^<]*<
. (Penafian: jelas itu masih tidak mudah, yang merupakan inti dari pertanyaan.)Saya tergoda untuk mengatakan "jangan menciptakan kembali roda". Kecuali bahwa XML benar-benar, sangat kompleks. Jadi mungkin saya harus mengatakan "jangan menemukan kembali synchrotron."
Mungkin klise yang benar dimulai "ketika semua yang Anda miliki adalah palu ..." Anda tahu bagaimana menggunakan ekspresi reguler, ekspresi reguler bagus untuk parsing, jadi mengapa repot-repot belajar parsing pustaka XML?
Karena parsing XML itu sulit . Upaya apa pun yang Anda hemat dengan tidak harus belajar menggunakan parsing pustaka XML akan lebih dari sekadar dibuat oleh jumlah karya kreatif dan bug-swatting yang harus Anda lakukan. Demi kepentingan Anda sendiri, google "perpustakaan XML" dan memanfaatkan karya orang lain.
sumber
Saya percaya klasik ini memiliki informasi yang Anda cari. Anda dapat menemukan poin di salah satu komentar di sana:
Beberapa info lagi dari Wikipedia: Chomsky Hierarchy
sumber
Saya pikir masalahnya bermuara pada:
Regex hampir selalu salah. Ada input yang sah yang tidak akan cocok dengan benar. Jika Anda bekerja cukup keras, Anda dapat membuatnya 99% benar, atau 99,999%, tetapi menjadikannya 100% benar hampir tidak mungkin, jika hanya karena hal-hal aneh yang memungkinkan XML dengan menggunakan entitas.
Jika regex salah, bahkan untuk 0,00001% input, maka Anda memiliki masalah keamanan, karena seseorang dapat menemukan satu input yang akan merusak aplikasi Anda.
Jika regex cukup benar untuk mencakup 99,99% dari kasus maka itu akan benar-benar tidak dapat dibaca dan tidak dapat dipelihara.
Sangat mungkin bahwa regex akan berkinerja sangat buruk pada file input berukuran sedang. Pertemuan pertama saya dengan XML adalah untuk mengganti skrip Perl yang (secara tidak benar) mem-parsing dokumen XML yang masuk dengan parser XML yang tepat, dan kami tidak hanya mengganti 300 baris kode yang tidak dapat dibaca dengan 100 baris yang dapat dipahami siapa pun, tetapi kami meningkatkan waktu respons pengguna dari 10 detik hingga sekitar 0,1 detik.
sumber
Saya tidak setuju. Jika Anda akan menggunakan rekursif dalam regex, Anda dapat dengan mudah menemukan tag buka dan tutup.
Di sini saya menunjukkan contoh regex untuk menghindari kesalahan parsing contoh dalam pesan pertama.
sumber
Saya memberikan jawaban yang disederhanakan untuk masalah ini di sini . Meskipun tidak memperhitungkan tanda 100%, saya menjelaskan bagaimana itu mungkin jika Anda bersedia melakukan beberapa pekerjaan pra-pemrosesan.
sumber