Bagaimana saya bisa membedakan dua file XML?

75

Di Linux, bagaimana saya bisa menghasilkan perbedaan antara dua file XML?

Idealnya, saya ingin dapat mengkonfigurasinya ke beberapa hal yang ketat, atau melonggarkan beberapa hal, seperti spasi, atau urutan atribut.

Saya akan sering peduli bahwa file-file tersebut secara fungsional sama, tetapi berbeda dengan sendirinya, akan mengganggu untuk digunakan, terutama jika file XML tidak memiliki banyak linebreak.

Sebagai contoh, berikut ini harus benar-benar baik-baik saja bagi saya:

<tag att1="one" att2="two">
  content
</tag>

<tag att2="two" att1="one">
  content
</tag>
qedi
sumber

Jawaban:

86

Salah satu pendekatan adalah pertama mengubah kedua file XML menjadi Canonical XML , dan membandingkan hasilnya menggunakan diff. Misalnya, xmllint dapat digunakan untuk mengkanonikkan XML.

$ xmllint --c14n one.xml > 1.xml
$ xmllint --c14n two.xml > 2.xml
$ diff 1.xml 2.xml

Atau sebagai one-liner.

$ diff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)
Jukka Matilainen
sumber
1
Tidak pernah tahu tentang saklar --c14n di xmllint. Itu berguna.
qedi
18
Anda dapat melakukannya dalam satu baris jugavimdiff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)
Nathan Villaescusa
dan xmllint dikirimkan bersama OS X
ClintM
10
Dalam kasus itu tidak jelas, c14n adalah singkatan untuk kanonikalisasi .
Brandin
3
Lebih baik untuk mengeksekusi langkah tambahan sebelum melakukan format kedua XML (xmllint --format). Karena saya perhatikan bahwa tanpa langkah ini, diff menunjukkan lebih banyak perbedaan daripada yang diperlukan.
ka3ak
23

Jawaban Jukka tidak bekerja untuk saya, tetapi itu menunjuk ke Canonical XML. Baik --c14n atau --c14n11 tidak mengurutkan atribut, tetapi saya memang menemukan saklar --exc-c14n yang mengurutkan atribut. --exc-c14n tidak terdaftar di halaman manual, tetapi dijelaskan pada baris perintah sebagai "format kanonik eksklusif W3C".

$ xmllint --exc-c14n one.xml > 1.xml
$ xmllint --exc-c14n two.xml > 2.xml
$ diff 1.xml 2.xml

$ xmllint | grep c14
    --c14n : save in W3C canonical format v1.0 (with comments)
    --c14n11 : save in W3C canonical format v1.1 (with comments)
    --exc-c14n : save in W3C exclusive canonical format (with comments)

$ rpm -qf /usr/bin/xmllint
libxml2-2.7.6-14.el6.x86_64
libxml2-2.7.6-14.el6.i686

$ cat /etc/system-release
CentOS release 6.5 (Final)

Peringatan --exc-c14n menghapus header xml sedangkan --c14n menambahkan header xml jika tidak ada.

rjt
sumber
18

Mencoba menggunakan jawaban @Jukka Matilainen tetapi memiliki masalah dengan white-space (salah satu file adalah satu-liner besar). Menggunakan --formatbantuan untuk melewati perbedaan ruang putih.

xmllint --format one.xml > 1.xml  
xmllint --format two.xml > 2.xml  
diff 1.xml 2.xml  

Catatan: Gunakan vimdiffperintah untuk perbandingan xmls berdampingan.

GuruM
sumber
Dalam kasus saya two.xmldihasilkan one.xmloleh skrip. Jadi saya hanya perlu memeriksa apa yang ditambahkan / dihapus oleh skrip.
GuruM
1
Ini adalah opsi yang saya butuhkan. Seharusnya versi yang paling kanonik dapat diperoleh dengan menggabungkan --formatdengan --exc-c14n; mungkin akan lebih lambat untuk memproses :(
ᴠɪɴᴄᴇɴᴛ
Sudah cukup lama sejak saya menulis jawabannya, tapi saya samar-samar ingat menggunakan flag --exc-c14n. Namun, membedakan output dengan / tanpa flag tidak menunjukkan perbedaan sehingga berhenti menggunakannya. Menjatuhkan bendera yang tidak perlu / tidak terpakai mungkin membuat proses lebih cepat.
GuruM
5
The --exc-c14npilihan menentukan pengurutan atribut. Dalam file spesifik Anda, atribut mungkin sudah diurutkan, tetapi saran umum adalah menggunakan kombinasi --format --exc-c14n.
ᴠɪɴᴄᴇɴᴛ
6

Diffxml mendapatkan fungsionalitas dasar yang benar, meskipun sepertinya tidak menawarkan banyak opsi untuk konfigurasi.

Sunting: Project Diffxml telah dimigrasikan ke GitHub sejak 2013.

dsolimano
sumber
Belum ada di sana, tapi setidaknya terlihat menjanjikan.
qedi
tidak berguna untuk file besar, mati setelah makan 40GB (RAM + SWAP) ketika membandingkan dua file ~ masing
Grzegorz
perhatikan bahwa proyek tersebut tampaknya sudah mati, dengan pembaruan terakhir pada 2013
Mateusz Konieczny
4

Jika Anda ingin juga mengabaikan urutan elemen anak, saya menulis alat python sederhana untuk ini yang disebut xmldiffs:

Bandingkan dua file XML, abaikan elemen dan urutan atribut.

Pemakaian: xmldiffs [OPTION] FILE1 FILE2

Setiap opsi tambahan diteruskan ke diffperintah.

Dapatkan di https://github.com/joh/xmldiffs

joh
sumber
1

Skrip Python saya xdiff.py untuk membandingkan file XML mengabaikan perbedaan dalam whitespace atau urutan atribut (berbeda dengan urutan elemen).

Untuk membandingkan dua file 1.xmldan 2.xml, Anda akan menjalankan skrip sebagai berikut:

xdiff.py 1.xml 2.xml

Dalam contoh OP, itu tidak akan menghasilkan apa-apa dan mengembalikan status keluar 0(tanpa perbedaan struktural atau tekstual).

Dalam kasus di mana 1.xmldan 2.xmlberbeda secara struktural, ini meniru keluaran terpadu dari GNU diff dan mengembalikan status keluar 1. Ada berbagai opsi untuk mengontrol output, seperti -auntuk mengeluarkan semua konteks, -nuntuk mengeluarkan tidak ada konteks, dan -quntuk menekan output sama sekali (sambil tetap mengembalikan status keluar).

Andreas Nolda
sumber
0

Saya menggunakan Beyond Compare untuk membandingkan semua jenis file berbasis teks. Mereka menghasilkan versi untuk Windows dan Linux.

Alan
sumber
1
Perbandingan teks biasa akan mengatakan dua baris berbeda, sedangkan OP ingin keduanya dilaporkan sama.
ChrisF
4
yaitu Canonically membandingkan XML.
Chris W. Rea,
1
Beyond Compare benar-benar menyebalkan untuk ini. Tampaknya tidak menyadari elemen XML dan melakukan sebagian besar hanya perbandingan teks.
Rob K
Beyond Compare memiliki plugin XML tetapi saya tidak pernah dapat menginstalnya dengan benar, jadi ... Nyeah ... Saya datang ke halaman ini dan menjadi lebih bijaksana ...
Erk
-1

Kami SD Cerdas Differencer membandingkan dokumen berdasarkan struktur sebagai lawan tata letak yang sebenarnya.

Ada XML Smart Differencer. Untuk XML, itu artinya mencocokkan urutan tag dan konten. Perlu dicatat bahwa string teks dalam fragmen spesifik yang Andaindikasikan berbeda. Itu saat ini tidak memahami gagasan XML atribut tag yang menunjukkan apakah spasi putih dinormalisasi vs signifikan.

Ira Baxter
sumber
1
Dalam profil SO Anda, Anda memberikan pengungkapan penuh tentang majikan Anda; Saya lebih suka disclaimer pendek di dalam jawaban Anda juga :) BTW, saya mencoba mengunduh salinan evaluasi, tetapi formulir permintaannya 'pintar' (melalui JS) cukup untuk menonaktifkan kombinasi XML dengan Smart Differencer (juga yang terakhir dalam kombinasi dengan Python, meskipun mungkin menurut halaman produk SD)?
ᴠɪɴᴄᴇɴᴛ
1
Ah. Terima kasih atas pengingatnya. Ini adalah jawaban dari waktu sebelum ada kebijakan SO yang jelas tentang ini. Saya merevisi jawaban untuk memberi sinyal hubungan dalam jawaban yang sesuai dengan kebijakan SO.
Ira Baxter
Saya akan memeriksa halaman unduhan; tidak semua produk langsung kami masuk ke dalam daftar itu. Ya, ini ada.
Ira Baxter
Saya memeriksa halaman unduhan. Ya, pembeda pintar XML tidak ada di sana. Saya akan meminta orang-orang di ruang belakang memperbaiki itu; harus ada paling tidak 1-2 minggu (mereka memiliki tumpukan, bukankah kita semua?) Sementara itu, jika Anda ingin mencobanya, kirim email (lihat bio).
Ira Baxter
1
Halaman tertaut tidak memiliki kata "XML" di dalamnya.
Mateusz Konieczny
-1

Tidak yakin apakah (ketergantungan) alat online dianggap sebagai solusi tetapi, untuk apa nilainya, saya mendapat hasil yang baik dalam alat perbandingan XML online ini . Itu hanya bekerja.

RayLuo
sumber