Wie kann ich zwei XML-Dateien unterscheiden?


75

Wie kann ich unter Linux einen Unterschied zwischen zwei XML-Dateien erzeugen?

Idealerweise würde ich es gerne in der Lage sein, einige Dinge streng zu konfigurieren oder einige Dinge zu lockern, wie Leerzeichen oder Attributreihenfolge.

Es ist mir oft wichtig, dass die Dateien funktional identisch sind, sich jedoch von selbst unterscheiden. Die Verwendung wäre ärgerlich, insbesondere wenn die XML-Datei nicht viele Zeilenumbrüche enthält.

Zum Beispiel sollte mir Folgendes wirklich recht sein:

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

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

Antworten:


86

Ein Ansatz wäre, zunächst beide XML-Dateien in kanonisches XML umzuwandeln und die Ergebnisse mithilfe von zu vergleichen diff. Beispielsweise kann mit xmllint XML kanonisiert werden.

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

Oder als Einzeiler.

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

1
Ich wusste nie über den Schalter --c14n in xmllint Bescheid. Das ist praktisch.
QEDI

18
Sie können es auch in einer Zeile tunvimdiff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)
Nathan Villaescusa

und xmllint werden mit OS X
ClintM

10
Für den Fall , es war nicht offensichtlich, C14N ist eine Abkürzung für die Kanonisierung .
Brandin

3
Es ist besser, vor dem Diff-Formatieren beider XMLs einen zusätzlichen Schritt auszuführen (xmllint -format). Denn mir ist aufgefallen, dass diff ohne diesen Schritt mehr Unterschiede aufweist als nötig.
Ka3ak

23

Die Antwort von Jukka hat bei mir nicht funktioniert, zeigte aber auf Canonical XML. Weder --c14n noch --c14n11 haben die Attribute sortiert, aber ich habe festgestellt, dass der Schalter --exc-c14n die Attribute sortiert hat. --exc-c14n ist nicht in der Manpage aufgeführt, wird jedoch in der Befehlszeile als "exklusives kanonisches W3C-Format" beschrieben.

$ 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)

Warnung --exc-c14n entfernt den xml-Header, wohingegen --c14n dem xml-Header vorangeht, falls nicht vorhanden.


18

Versuchte die Antwort von @Jukka Matilainen zu verwenden, hatte aber Probleme mit dem Leerraum (eine der Dateien war ein riesiger Einzeiler). Mit können Sie --formatLeerraumunterschiede überspringen.

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

Hinweis: Verwenden Sie den vimdiffBefehl für den direkten Vergleich der XML-Dateien.


In meinem Fall two.xmlwurde one.xmlvon einem Skript generiert . Also musste ich nur überprüfen, was vom Skript hinzugefügt / entfernt wurde.
GuruM

1
Dies war die Option, die ich brauchte. Angeblich kann die kanonischste Version erhalten werden, indem man --formatmit kombiniert --exc-c14n; wird wahrscheinlich noch langsamer zu verarbeiten sein :(
ᴠɪɴᴄᴇɴᴛ

Es ist schon einige Zeit vergangen, seit ich die Antwort geschrieben habe, aber ich erinnere mich schwach an die Verwendung des Flags --exc-c14n. Da die Ausgabe mit / ohne Flag jedoch keine Unterschiede aufwies, haben Sie einfach aufgehört, sie zu verwenden. Das Löschen unnötiger / nicht verwendeter Flags kann den Prozess beschleunigen.
GuruM

5
Die --exc-c14nOption legt die Sortierung der Attribute fest. In Ihren spezifischen Dateien wurden die Attribute wahrscheinlich bereits sortiert, aber der allgemeine Rat wäre, die Kombination zu verwenden --format --exc-c14n.
22.

6

Diffxml stellt die Grundfunktionalität korrekt dar, obwohl es nicht viele Konfigurationsoptionen zu bieten scheint.

Bearbeiten: Project Diffxml wird seit 2013 auf GitHub migriert.


Es ist noch nicht ganz da, aber es sieht zumindest vielversprechend aus.
QEDI

Nicht nützlich für große Dateien, starb nach dem Essen von 40 GB (RAM + SWAP) beim Vergleich von zwei Dateien ~ 20.000 Zeilen
Grzegorz

Beachten Sie, dass das Projekt anscheinend tot ist, mit dem letzten Update im Jahr 2013
Mateusz Konieczny

4

Wenn Sie auch die Reihenfolge der untergeordneten Elemente ignorieren möchten, habe ich ein einfaches Python-Tool dafür geschrieben xmldiffs:

Vergleichen Sie zwei XML-Dateien und ignorieren Sie dabei die Reihenfolge der Elemente und Attribute.

Verwendungszweck: xmldiffs [OPTION] FILE1 FILE2

Alle zusätzlichen Optionen werden an den diffBefehl übergeben.

Laden Sie es unter https://github.com/joh/xmldiffs herunter


1

Mein Python-Skript xdiff.py zum Vergleichen von XML-Dateien ignoriert Unterschiede in der Whitespace- oder Attributreihenfolge (im Gegensatz zur Elementreihenfolge).

Um zwei Dateien 1.xmlund zu vergleichen 2.xml, führen Sie das Skript wie folgt aus:

xdiff.py 1.xml 2.xml

Im Beispiel des OP würde es nichts ausgeben und den Exit-Status zurückgeben 0(für keine strukturellen oder textuellen Unterschiede).

In Fällen , in denen 1.xmlund 2.xmlstrukturell unterscheiden, imitiert er das einheitliche Ausgabe von GNU diff und Exit - Status zurückgibt 1. Es gibt verschiedene Möglichkeiten, die Ausgabe zu steuern, z. B. den -agesamten Kontext auszugeben, -nkeinen Kontext -qauszugeben und die Ausgabe insgesamt zu unterdrücken (während weiterhin der Beendigungsstatus zurückgegeben wird).


0

Ich benutze Beyond Compare , um alle Arten von textbasierten Dateien zu vergleichen. Sie produzieren Versionen für Windows und Linux.


1
Vergleiche im Klartext würden bedeuten, dass sich die beiden Zeilen unterscheiden, während das OP möchte, dass sie als gleich gemeldet werden.
ChrisF

4
dh Canonisch vergleichen Sie die XML.
Chris W. Rea

1
Beyond Compare ist wirklich scheiße dafür. Es scheint nur keine Kenntnis von XML-Elementen zu haben und meist nur einen Textvergleich durchzuführen.
Rob K

Beyond Compare hat ein XML-Plugin, aber ich konnte es nie richtig installieren, also ... Nyeah ... ich bin auf diese Seite gekommen und wurde weiser ...
Erk

-1

Unser SD Smart Differencer vergleicht Dokumente anhand der Struktur und nicht anhand des tatsächlichen Layouts.

Es gibt einen XML Smart Differencer. Für XML bedeutet dies, dass die Reihenfolge der Tags und des Inhalts übereinstimmt. Es sollte beachtet werden, dass die Textzeichenfolge in dem angegebenen Fragment unterschiedlich war. Derzeit wird der XML-Begriff der Tag-Attribute nicht verstanden, der angibt, ob Leerzeichen normalisiert oder signifikant sind.


1
In Ihrem SO-Profil machen Sie vollständige Angaben zu Ihrem Arbeitgeber. Ich hätte auch einen kurzen Haftungsausschluss in Ihrer Antwort vorgezogen :) Übrigens, ich habe versucht, eine Testversion herunterzuladen, aber das Anforderungsformular ist (über JS) genug, um die Kombination XML mit Smart Differencer (auch letzteres) zu deaktivieren in Kombination mit Python, obwohl laut SD-Produktseite möglich)?
27.

1
Ah. Danke für die Erinnerung. Dies ist eine Antwort aus einer Zeit, bevor es eine klare SO-Richtlinie dazu gab. Ich überarbeite die Antwort, um die Beziehung in der SO-Richtlinien-kompatiblen Antwort anzuzeigen.
Ira Baxter

Ich überprüfe die Downloadseite. Nicht alle unsere Live-Produkte werden in diese Liste aufgenommen. Ja, das gibt es.
Ira Baxter

Ich habe die Downloadseite überprüft. Ja, der XML Smart Differencer ist nicht da. Ich lasse die Leute im Hinterzimmer daran arbeiten, das zu reparieren. sollte in maximal 1-2 Wochen da sein (sie haben einen Rückstand, nicht wahr?) In der Zwischenzeit, wenn Sie es versuchen möchten, senden Sie eine E-Mail (siehe Bio).
Ira Baxter

1
Die verknüpfte Seite enthält kein Wort "XML".
Mateusz Konieczny

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.