Come posso diff due file XML?


75

Su Linux, come posso generare una differenza tra due file XML?

Idealmente, vorrei essere in grado di configurarlo su alcune cose rigorose o allentare alcune cose, come gli spazi bianchi o l'ordine degli attributi.

Mi preoccuperò spesso che i file siano funzionalmente uguali, ma diff da soli, sarebbero noiosi da usare, specialmente se il file XML non ha molte interruzioni di riga.

Ad esempio, per me dovrebbe davvero andare bene:

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

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

Risposte:


86

Un approccio sarebbe quello di trasformare prima entrambi i file XML in XML canonico e confrontare i risultati usando diff. Ad esempio, xmllint può essere utilizzato per canonicalizzare XML.

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

O come one-liner.

$ diff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)

1
Non ho mai saputo dell'opzione --c14n in xmllint. È utile.
Qedi

18
Puoi farlo anche in una rigavimdiff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)
Nathan Villaescusa

e xmllint viene fornito con OS X
ClintM il

10
Nel caso in cui non fosse ovvio, c14n è un'abbreviazione per canonicalizzazione .
Brandin,

3
È meglio eseguire un passaggio aggiuntivo prima della diff - formattazione di entrambi gli XML (xmllint --format). Perché ho notato che senza questo passaggio diff mostra più differenze del necessario.
Ka3ak,

23

La risposta di Jukka non ha funzionato per me, ma ha fatto riferimento a XML canonico. Né --c14n--c14n11 hanno ordinato gli attributi, ma ho trovato che l' opzione --exc-c14n ha ordinato gli attributi. --exc-c14n non è elencato nella pagina man, ma descritto nella riga di comando come "formato canonico esclusivo 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)

Avvertenza --exc-c14n rimuove l'intestazione xml mentre --c14n antepone l'intestazione xml se non è presente.


18

Ho provato ad usare la risposta di @Jukka Matilainen ma ho avuto problemi con lo spazio bianco (uno dei file era un enorme one-liner). L'utilizzo --formataiuta a saltare le differenze di spazio bianco.

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

Nota: utilizzare il vimdiffcomando per il confronto side-by-side degli xmls.


Nel mio caso è two.xmlstato generato one.xmlda una sceneggiatura. Quindi dovevo solo controllare cosa era stato aggiunto / rimosso dallo script.
GuruM,

1
Questa era l'opzione di cui avevo bisogno. Presumibilmente la versione più canonica può essere ottenuta combinando --formatcon --exc-c14n; probabilmente sarà ancora più lento da elaborare :(
ᴠɪɴᴄᴇɴᴛ

È passato un po 'di tempo da quando ho scritto la risposta, ma ricordo vagamente di aver usato la bandiera --exc-c14n. Tuttavia, diffondere l'output con / senza il flag non ha mostrato differenze, quindi ha smesso di usarlo. La caduta di flag non necessari / non utilizzati potrebbe rendere il processo più veloce.
GuruM,

5
L' --exc-c14nopzione specifica l'ordinamento degli attributi. Nei tuoi file specifici gli attributi probabilmente erano già stati ordinati, ma il consiglio generale sarebbe di usare la combinazione --format --exc-c14n.
ᴠɪɴᴄᴇɴᴛ

6

Diffxml ottiene la funzionalità di base corretta, anche se non sembra offrire molte opzioni per la configurazione.

Modifica: Project Diffxml è stato migrato su GitHub dal 2013.


Non è ancora del tutto lì, ma sembra almeno promettente.
Qedi

non utile per file di grandi dimensioni, è morto dopo aver mangiato 40 GB (RAM + SWAP) confrontando due file ~ 20k linee ciascuno
Grzegorz,

notare che il progetto sembra essere morto, con l'ultimo aggiornamento nel 2013
Mateusz Konieczny,

4

Se desideri ignorare anche l'ordine degli elementi figlio, ho scritto un semplice strumento Python per questo chiamato xmldiffs:

Confronta due file XML, ignorando l'elemento e l'ordine degli attributi.

Uso: xmldiffs [OPTION] FILE1 FILE2

Eventuali opzioni extra vengono passate al diffcomando.

Scaricalo su https://github.com/joh/xmldiffs


1

Il mio script Python xdiff.py per il confronto di file XML ignora le differenze negli spazi bianchi o nell'ordine degli attributi (in contrasto con l'ordine degli elementi).

Per confrontare due file 1.xmle 2.xml, eseguire lo script come segue:

xdiff.py 1.xml 2.xml

Nell'esempio del PO, non produrrebbe nulla e restituirebbe lo stato di uscita 0(senza differenze strutturali o testuali).

Nei casi in cui 1.xmle 2.xmldifferiscono strutturalmente, imita l'output unificato del GNU diff e restituisce lo stato di uscita 1. Esistono varie opzioni per controllare l'output, ad esempio -aper emettere tutto il contesto, -nper non generare alcun contesto e -qper sopprimere del tutto l'output (pur continuando a restituire lo stato di uscita).


0

Uso Beyond Compare per confrontare tutti i tipi di file basati su testo. Producono versioni per Windows e Linux.


1
Confronti in testo semplice direbbero che le due righe differivano, mentre l'OP vuole che vengano riportate come uguali.
ChrisF,

4
cioè confrontare canonico l'XML.
Chris W. Rea,

1
Beyond Compare fa davvero schifo per questo. Sembra semplicemente non essere a conoscenza degli elementi XML e fare principalmente solo il confronto testuale.
Rob K,

Beyond Compare ha un plug-in XML ma non sono mai stato in grado di installarlo correttamente, quindi ... Nyeah ... Sono arrivato a questa pagina e sono diventato più saggio ...
Erk

-1

Il nostro SD Smart Differencer confronta i documenti in base alla struttura anziché al layout effettivo.

C'è un differenziale intelligente XML. Per XML, ciò significa ordine corrispondente di tag e contenuto. Dovrebbe notare che la stringa di testo nel frammento specifico che hai indicato era diversa. Attualmente non comprende la nozione XML di attributi di tag che indica se lo spazio bianco è normalizzato rispetto a significativo.


1
Nel tuo profilo SO fornisci informazioni complete sul tuo datore di lavoro; Avrei preferito un breve disclaimer anche nella tua risposta :) A proposito, ho provato a scaricare una copia di valutazione, ma il modulo di richiesta è abbastanza "intelligente" (via JS) da disabilitare la combinazione XML con Smart Differencer (anche quest'ultimo in combinazione con Python, sebbene possibile secondo la pagina del prodotto SD)?
ᴠɪɴᴄᴇɴᴛ

1
Ah. Grazie per il promemoria. Questa è una risposta di un tempo prima che ci fosse una chiara politica SO su questo. Sto rivedendo la risposta per segnalare la relazione nella risposta conforme alla politica SO.
Ira Baxter,

Controllerò la pagina di download; non tutti i nostri prodotti live fanno parte di tale elenco. Sì, questi esistono.
Ira Baxter,

Ho controllato la pagina di download. Sì, il differenziatore intelligente XML non è presente. Farò in modo che i ragazzi dietro le quinte lavorino per risolverlo; dovrebbe essere lì in 1-2 settimane al massimo (hanno un arretrato, non tutti?) Nel frattempo, se vuoi provarlo, invia un'e-mail (vedi biografia).
Ira Baxter,

1
La pagina collegata non contiene la parola "XML".
Mateusz Konieczny il

-1

Non sono sicuro se (la dipendenza di) uno strumento online sia considerato una soluzione, ma, per quello che vale, ho ottenuto buoni risultati in questo strumento di confronto XML online . Funziona semplicemente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.