Diff-Tool für XML-Dateien?

Ich suche ein Windows-basiertes Diff-Tool, das mir die Unterschiede zwischen zwei XML-Dateien anzeigt, dies jedoch baumbasiert und nicht zeilenbasiert macht .
Das heißt, wenn ein Abschnitt an eine völlig andere Stelle in der Datei verschoben wurde, sollte er keine Unterschiede melden.
Diese beiden Dateien sollten als "gleich" gemeldet werden:

<soapenv:Body>
  <mes:GetItem>
    <mes:ItemShape>
      <typ:BaseShape>IdOnly</typ:BaseShape>
      <typ:BodyType>Text</typ:BodyType>
      <typ:AdditionalProperties>
        <typ:FieldURI FieldURI="item:Subject" />
        <typ:FieldURI FieldURI="item:Categories" />
      </typ:AdditionalProperties>
    </mes:ItemShape>
    <mes:ItemIds>
      <typ:ItemId Id="AAMYAAA="/>
    </mes:ItemIds>
  </mes:GetItem>
</soapenv:Body>


<soapenv:Body>
  <mes:GetItem>
    <mes:ItemIds>
      <typ:ItemId Id="AAMYAAA="/>
    </mes:ItemIds>
    <mes:ItemShape>
      <typ:BodyType>Text</typ:BodyType>
      <typ:BaseShape>IdOnly</typ:BaseShape>
      <typ:AdditionalProperties>
        <typ:FieldURI FieldURI="item:Categories" />
        <typ:FieldURI FieldURI="item:Subject" />
      </typ:AdditionalProperties>
    </mes:ItemShape>
  </mes:GetItem>
</soapenv:Body>

Und natürlich sollten alle Unterschiede markiert werden, vorzugsweise in einer Seite-an-Seite-Ansicht mit Indikatoren oder Linien, die die unterschiedlichen Abschnitte verbinden.

Kostenlos wäre schön.
Optional Namensräume zu ignorieren wäre nett.

Mögliches Duplikat von Free XML Compare Tool
@rrirower ja, aber es wurde dort geschlossen: / Stack Exchange hat diese Tendenz, zu schließen, anstatt zu migrieren.
Jan, haben Sie die gängigsten Diff-Programme unter Windows wie WinMerge2011 ausprobiert, um zu sehen, ob sie eine Option für diese Funktionalität haben? (Beachten Sie, dass WinMerge2011 seit dem letzten Update des regulären WinMerge viele Updates erhalten hat, auch wenn der Name das Gegenteil impliziert.)
Altova, altova.com/xml_tools.html , stellt den hervorragenden XML Spy her , der diese Fähigkeit haben könnte. Es gibt keine aktuelle kostenlose Version, aber eine kostenlose 30-Tage-Testversion kann heruntergeladen werden. Siehe auch alternativeto.net/software/altova-xmlspy .
So einen könnte ich auch gebrauchen.
"als 'gleich' gemeldet" ... Diese XML-Dateien sind nur dann "gleich", wenn Sie darauf bestehen, dass die Reihenfolge einiger Tags irrelevant ist. Für manche Leute spielt die Reihenfolge eine Rolle . Sie benötigen ein Schema oder ein anderes Signal, um anzuzeigen, welcher Fall für welche Tags verwendet wird.
Beyond Compare hat spezielle Funktionen für XML. Sehen Sie sich Zusätzliche Dateiformate für XML an.
Ich dachte nur, durch das Laden beider XML-Dateien in den Speicher könnte sogar ein xmlstarlet-Patch erstellt werden, da im Speicher die Reihenfolge keine Rolle spielt und jedes Element einzigartig ist (im Falle einer Duplizität). Wenn jemand dies tut, bitte in Java oder zumindest einem Linux-kompatiblen OpenSource :)
Haben Sie nach 3 Jahren zufällig eine Lösung für Ihr Problem gefunden?
@Mast Meine aktuelle Arbeit braucht das nicht mehr, also habe ich das auf Sparflamme. Ich plane jedoch, diesen Beitrag noch einmal zu besuchen, wenn ich etwas Zeit finde.

Antworten (6)

Technisch gesehen sind XMLs anders

  • ob sie Leerzeichen haben oder nicht
  • wenn die Reihenfolge anders ist
  • ob sie Kommentare haben oder nicht
  • ob sie Verarbeitungsanweisungen haben oder nicht
  • wenn ihre Kodierung unterschiedlich ist
  • wenn ihre Namensräume unterschiedlich sind

aber natürlich können Sie entscheiden, ob Sie dies ignorieren oder nicht, basierend auf den semantischen Informationen, die ein XML nicht hat.

Microsoft hat für diesen Zweck das Tool XML Diff and Patch entwickelt, das Sie in Ihre eigenen Anwendungen integrieren können .

Hinweis: Das Tool wird als "SQLXML Bulkload in .NET Code Sample" installiert und enthält eine Visual Studio-Lösung XmlDiffView.sln, die Sie selbst kompilieren müssen. Einige grundlegende Programmierkenntnisse in C# und Visual Studio Community Edition sollten in Ordnung sein.

Wie in einer der Antworten auf Stack Overflow erwähnt , wurde es jedoch kompiliert und auf Bitbucket verfügbar gemacht .

Danach kommt es mit einer Benutzeroberfläche, mit der Sie die verschiedenen XML-Vergleichsoptionen auswählen können:

XmlDiff-Benutzeroberfläche

Wenn ich es auf die 2 XMLs Ihrer Fragen anwende, wird eine Ausnahme ausgelöst. Das liegt an den nicht definierten Namespaces. Nach dem Entfernen der Namespaces heißt es:

Dateien identisch für die angegebenen Optionen

Vielen Dank. Ich habe diese Antwort positiv bewertet, aber nicht als richtig markiert. Grund: Die Oberfläche des Ergebnisfensters des GUI-Tools ist schrecklich: Beim Vergleich zweier großer XML-Dateien ist das Diff-Fenster etwa 3000 Pixel breit, enthält alle identischen XML-Dateien und hat keine Bildlaufleisten. Versuchen Sie dann, die Unterschiede zwischen zwei 55-MB-Dateien zu finden ;-( Ich bin kein Cx-Programmierer, daher kann ich das Programm nicht anpassen.
@JanDoggen: Ja, ich stimme zu, es ist sehr entwicklerorientiert. Ohne Programmierkenntnisse ist es kaum zu bedienen.
@JanDoggen Die Bildlaufleiste ist ein winziger, nur wenige Pixel breiter Streifen am rechten Rand des Fensters. Ich stimme zu, dass die Ausgabe nicht sehr hübsch ist, aber es ist immer noch ein nützliches Werkzeug.
@ThomasWeller +1 für den Link zu BitBucket. Ich habe kompiliert, hatte aber kein Glück, die Originalquelle zum Laufen zu bringen.

Die Konzentration auf den Teil, dass verschobene Abschnitte gemeldet werden sollten, da kein Unterschied vorhanden war, ließ mich an https://semanticmerge.com/ denken , das keine XML-Dateien, sondern C#- und C-Code vergleicht. Und da es diese Sprachen versteht, kann es anzeigen, ob der Code verschoben und nicht geändert wurde.

Dies führt zu einem alternativen Ansatz für diese Frage: Könnte es möglich sein, das XML in C#-Klassen zu übersetzen und dann eine semantische Zusammenführung des resultierenden Codes durchzuführen?

Ein möglicher Ansatz, falls dieses Tool noch nicht geschrieben wurde, könnte darin bestehen, jedes einzelne Element in Klassen und jedes Attribut (und den Haupttext) in eine Zeichenfolgeneigenschaft innerhalb dieser Klasse zu übersetzen. Wenn Sie Namensräume ignorieren möchten, lassen Sie sie von Ihrem Übersetzer im Übersetzungsprozess entfernen.

Ich habe das als Proof of Concept angegebene XML-Beispiel übersetzt und Folgendes erhalten:

class soapenv__Body {
  class mes__GetItem {
    class mes__ItemShape {
      class typ__BaseShape {
          string body="IdOnly";
      }
      class typ__BodyType {
          string body="Textus";
      }
      class typ__AdditionalProperties {
        class typ__FieldURI  {
            string FieldURI="item:Subject";
        }
        class typ__FieldURI  {
            string FieldURI="item:Categories"; 
        }
      }
    }
    class mes__ItemIds {
      class typ__ItemId {
          string Id="AAMYAAA=";
      }
    }
  }
}

Dann habe ich das mes:ItemIdsund mes:ItemShapevertauscht und den Text in geändert Textus. Verglich die folgenden zwei Dateien in Semantic Merge und erhielt das folgende Bild:

Screenshot der semantischen Zusammenführung

In diesem Bild kann man die Bewegung sehen, die durch das MSymbol angezeigt wird, und die Textänderung, die durch das CSymbol angezeigt wird. Linien zeigen an, wo sich die verschiedenen Teile bewegt/geändert haben, und es ist möglich, die Unterschiede tatsächlich zu sehen, falls vorhanden.

Beachten Sie, dass Semantic Merge, obwohl es C#-Code versteht, nicht zu streng auf die identischen Klassennamen von typ__FieldURIist, was ein nettes Feature sein könnte, da XML mehrere Knoten mit demselben Namen enthalten kann.

Summa summarum: Semantic Merge kann XML korrekt als identisch (oder nicht) identifizieren, obwohl Elemente verschoben werden, wenn Sie das XML in eine C#-Klassenstruktur konvertieren können.

Nur zum Spaß habe ich versucht, die typ:FieldUriElemente zu verschieben, und Semantic Merge hat sie korrekt als verschoben identifiziert. So wird die Reihenfolge korrekt erkannt und Sie können die Reihenfolge der Attribute verfolgen, wenn Sie dies wünschen.

Technisch gesehen sind diese nicht gleich (zumindest in XML), die Reihenfolge spielt eine Rolle, es sei denn, dies ist im Schema explizit angegeben.

Eine Kombination aus xmlstarlet und normalen zeilenbasierten Dienstprogrammen kann das Problem viel besser handhabbar machen.

Das Folgende vergleicht nur die Struktur, könnte aber erweitert werden, um die Attribute, ihre Werte und den Text zu betrachten

xmlstarlet el snippet1-with-namespaces.xml | sort > structure1.txt

xmlstarlet el snippet2-with-namespaces.xml | sort > structure2.txt

diff structure.txt structure2.txt

Nachdem Sie dies auf Ihren Snippets ausgeführt haben, zeigt der Diff keine Unterschiede, aber es gab einen Fehlertext zu Namespaces (der sicher ignoriert werden kann).

Ich würde ein Tool XiMpLe empfehlen, das in erster Linie der XML-Editor ist, aber auch XML-Dateien auf übersichtliche Weise vergleichen (und zusammenführen) kann. Ihr Beispiel wird verglichen und als identisch bewertet. Es besteht auch die Möglichkeit, Namespaces aufzulösen.

Beispiel für das Vergleichsergebnis

Aktuell versuche ich ein ganz ähnliches Problem für mich zu lösen. Leider habe ich keine Bibliothek gefunden, die meinen Anforderungen entspricht, um eine SVG-Visualisierung eines XML-Vergleichs zu erstellen.

Deshalb habe ich eine Open-Source-Bibliothek gestartet, die vom X-Diff- Algorithmus inspiriert ist. Also nur zum Spaß und in der Hoffnung, jemanden zu finden, der die XmlXdiff- Bibliothek unterstützt. Bis jetzt ist es keine kugelsichere Bibliothek und noch im Aufbau, aber hier ist das Ergebnis für Ihr Beispiel-Snippet:

Geben Sie hier die Bildbeschreibung ein

Code, der dieses Ergebnis erzeugt:

    from XmlXdiff.XReport import DrawXmlDiff

    _xml1 = """<frame xmlns:soapenv="sn" xmlns:mes="meas" xmlns:typ="type">
    <soapenv:Body>
      <mes:GetItem>
        <mes:ItemShape>
          <typ:BaseShape>IdOnly</typ:BaseShape>
          <typ:BodyType>Text</typ:BodyType>
          <typ:AdditionalProperties>
            <typ:FieldURI FieldURI="item:Subject" />
            <typ:FieldURI FieldURI="item:Categories" />
          </typ:AdditionalProperties>
        </mes:ItemShape>
        <mes:ItemIds>
          <typ:ItemId Id="AAMYAAA="/>
        </mes:ItemIds>
      </mes:GetItem>
    </soapenv:Body>
    </frame>"""
    _xml2 = """<frame xmlns:soapenv="sn" xmlns:mes="meas" xmlns:typ="type">
    <soapenv:Body>
      <mes:GetItem>
        <mes:ItemIds>
          <typ:ItemId Id="AAMYAAA="/>
        </mes:ItemIds>
        <mes:ItemShape>
          <typ:BodyType>Text</typ:BodyType>
          <typ:BaseShape>IdOnly</typ:BaseShape>
          <typ:AdditionalProperties>
            <typ:FieldURI FieldURI="item:Categories" />
            <typ:FieldURI FieldURI="item:Subject" />
          </typ:AdditionalProperties>
        </mes:ItemShape>
      </mes:GetItem>
    </soapenv:Body>
    </frame>"""

    _path1 = '{}\\..\\..\\tests\\simple\\xml1.xml'.format(getPath())
    _path2 = '{}\\..\\..\\tests\\simple\\xml2.xml'.format(getPath())
    _out = '{}\\..\\..\\tests\\simple\\xdiff.svg'.format(getPath())

    with open(_path1, "w") as f:
        f.write(_xml1)

    with open(_path2, "w") as f:
        f.write(_xml2)

    x = DrawXmlDiff(_path1, _path2)
    x.draw()
    x.saveSvg(_out)

Zusammenfassend zu Ihren Anforderungen:

  1. Strukturbewusster, nicht zeilenbasierter Vergleich: Ja
  2. Kann unter Windows ausgeführt werden: Ja
  3. Orderloser Vergleich/Move Handling: Ja
  4. Side-by-Side-Vergleichsausgabe: Ja
  5. Ignorieren erwarteter Änderungen: Ja
  6. Kostenlos: Nein, aber eine kostenlose Testversion ist verfügbar.

XML Compare , entwickelt von DeltaXML, ist ein strukturbewusstes XML-Vergleichstool, das unter Windows sowie Linux und Mac mit Java ausgeführt werden kann. XML Compare kann über die Befehlszeile, die REST-API und die Java-API verwendet werden .

Die Diff-Ausgaben von XML Compare sind gültiges XML, was bedeutet, dass sie problemlos von anderen Anwendungen verarbeitet und über die Nachbearbeitungskonfiguration in andere Ausgabeformate umgewandelt werden können. Änderungen werden durch das Hinzufügen neuer Attribute in der Diff-Ausgabe identifiziert, die angeben, ob der Inhalt oder die Struktur in der A-Eingabe vorhanden war, in der B-Eingabe vorhanden war und ob er in beiden gleich ist oder sich geändert hat. Es folgt einem einfachen „A!=B“-Format, siehe das Beispiel-Snippet unten.

<height deltaxml:deltaV2="A!=B">
           <deltaxml:textGroup deltaxml:deltaV2="A!=B">
              <deltaxml:text deltaxml:deltaV2="A">up to 1.4 meters</deltaxml:text>
              <deltaxml:text deltaxml:deltaV2="B">up to 1.3 meters</deltaxml:text>
           </deltaxml:textGroup>
        </height>

In Bezug auf Ihre Anforderungen an die Berücksichtigung verschobener Inhalte ist XML Compare in hohem Maße konfigurierbar. Es gibt Dutzende von vorkonfigurierten Eingabe- und Ausgabeprozessoren und Filtern, und mit XSLT können benutzerdefinierte Pipelines und Filter erstellt werden.

Speziell für Ihre Anforderungen gibt es vorkonfigurierte Funktionen zum Vergleichen ordnungsloser Elemente im Falle eines Vergleichs, bei dem die Reihenfolge der Elemente nicht signifikant ist, zum Erkennen und Handhaben von Bewegungen und zum Ignorieren von Änderungen , wenn sie erwartet werden und nicht hervorgehoben werden müssen.

Schließlich ist eines der verfügbaren vorkonfigurierten Ausgabeformate ein Side-by-Side-HTML-Diff-Bericht , der auf der Delta-Ausgabe aufbaut. In Fällen, in denen Sie jedoch eine spezifischere Ausgabe benötigen, können Sie die Ausgabe erneut mit XSLT oder den vorhandenen Konfigurationsoptionen konfigurieren und verarbeiten. Unten ist ein Screenshot des Side-by-Side-Diff-Berichts:

DeltaXML nebeneinander HTML-Vergleichsbericht

Offenlegung: Ich bin ein Mitarbeiter von DeltaXML.

So wie es derzeit geschrieben steht, ist Ihre Antwort unklar. Bitte bearbeiten Sie , um zusätzliche Details hinzuzufügen, die anderen helfen zu verstehen, wie dies die gestellte Frage beantwortet. Weitere Informationen zum Verfassen guter Antworten finden Sie in der Hilfe .