Wie vergleiche ich zwei XML-Dateien mit denselben Daten in unterschiedlichen Zeilen?


9

Ich habe zwei Dateien mit den gleichen Daten, aber in unterschiedlichen Zeilen.

Datei 1:

<Identities>
    <Identity>
        <Id>048206031415072010Comcast.USR8JR</Id>
        <UID>ccp_test_79</UID>
        <DisplayName>JOSH CCP</DisplayName>
        <FirstName>JOSH</FirstName>
        <LastName>CCP</LastName>
        <Role>P</Role>
        <LoginStatus>C</LoginStatus>
    </Identity>
    <Identity>
        <Id>089612381523032011Comcast.USR1JR</Id>
        <UID>94701_account1</UID>
        <DisplayName>account1</DisplayName>
        <FirstName>account1</FirstName>
        <LastName>94701</LastName>
        <Role>S</Role>
        <LoginStatus>C</LoginStatus>
    </Identity>
</Identities>

Datei 2:

<Identities>
    <Identity>
        <Id>089612381523032011Comcast.USR1JR</Id>
        <UID>94701_account1</UID>
        <DisplayName>account1</DisplayName>
        <FirstName>account1</FirstName>
        <LastName>94701</LastName>
        <Role>S</Role>
        <LoginStatus>C</LoginStatus>
    </Identity>
    <Identity>
        <Id>048206031415072010Comcast.USR8JR</Id>
        <UID>ccp_test_79</UID>
        <DisplayName>JOSH CCP</DisplayName>
        <FirstName>JOSH</FirstName>
        <LastName>CCP</LastName>
        <Role>P</Role>
        <LoginStatus>C</LoginStatus>
    </Identity>
</Identities>

Wenn ich den diff file1 file2Befehl benutze, erhalte ich folgende Antwort:

1,10d0
<     <Identities>
<         <Identity>
<             <Id>048206031415072010Comcast.USR8JR</Id>
<             <UID>ccp_test_79</UID>
<             <DisplayName>JOSH CCP</DisplayName>
<             <FirstName>JOSH</FirstName>
<             <LastName>CCP</LastName>
<             <Role>P</Role>
<             <LoginStatus>C</LoginStatus>
<         </Identity>
20a11,20
>     <Identities>
>         <Identity>
>             <Id>048206031415072010Comcast.USR8JR</Id>
>             <UID>ccp_test_79</UID>
>             <DisplayName>JOSH CCP</DisplayName>
>             <FirstName>JOSH</FirstName>
>             <LastName>CCP</LastName>
>             <Role>P</Role>
>             <LoginStatus>C</LoginStatus>
>         </Identity>

Aber ich muss keinen Unterschied machen, weil diese Dateien die gleichen Daten in verschiedenen Zeilen haben.


Indem Sie sie zeilenweise sortieren und vergleichen, können Sie überprüfen, ob sie nicht gleich sind . Gleich nach dem Sortieren bedeutet natürlich nicht, dass sie wirklich gleich sind, da das Sortieren die XML-Syntax zerstört.
Jofel

Ich weiß nicht, wie ich es lösen soll. Sie unterscheiden sich nach Reihenfolge in Datei1a, dann b und in Datei2b, dann a. Sie können Frage mit diff -y -B -Z -b --strip-trailing-cr Datei1 Datei2
Yurij73

2
Sie könnten es versuchen xmldiff, aber ich denke, das wird immer noch eine Änderung der Reihenfolge bemerken, da die Reihenfolge in generischem XML relevant ist. Ich denke, Ihr bester Ansatz ist es, einen XML-Parser und -Generator zu verwenden, um jede Datei in eine kanonische Reihenfolge und ein kanonisches Format zu bringen, und dann xmldiffoder zu verwenden diff. Ein Job für Ihre bevorzugte Skriptsprache (Perl, Ruby, Python usw.).
Derobert

Antworten:


6

Sie können mit Hilfe eines kleinen Python-Skripts erreichen, was Sie möchten (Python muss installiert sein, ebenso wie das lxmlToolkit).

tagsort.py::

#!/usr/bin/python

import sys
from lxml import etree

filename, tag = sys.argv[1:]

doc = etree.parse(filename, etree.XMLParser(remove_blank_text=True))
root = doc.getroot()
root[:] = sorted(root, key=lambda el: el.findtext(tag))
print etree.tostring(doc, pretty_print=True)

Dieses Skript sortiert die Elemente der ersten Ebene unter dem XML-Dokumentstamm nach dem Inhalt eines Elements der zweiten Ebene und sendet das Ergebnis an stdout. Es heißt so:

$ python tagsort.py filename tag

Sobald Sie das haben, können Sie die Prozessersetzung verwenden , um ein Diff basierend auf seiner Ausgabe zu erhalten (ich habe ein Element hinzugefügt und ein anderes in Ihren Beispieldateien geändert, um ein nicht leeres Ergebnis anzuzeigen):

$ diff <(python tagsort.py file1 Id) <(python tagsort.py file2 Id)
4a5
>     <AddedTag>Something</AddedTag>
17c18
<     <Role>X</Role>
---
>     <Role>S</Role>

3

Ich hatte ein ähnliches Problem und fand schließlich: /superuser/79920/how-can-i-diff-two-xml-files

In diesem Beitrag wird vorgeschlagen, eine kanonische XML-Sortierung und dann einen Diff durchzuführen. Folgendes sollte für Sie funktionieren, wenn Sie unter Linux oder Mac arbeiten oder wenn Sie Windows wie Cygwin installiert haben:

$ xmllint --c14n File1.xml > 1.xml
$ xmllint --c14n File2.xml > 2.xml
$ diff 1.xml 2.xml

0

Es ist eine getaggte Shell, aber ehrlich gesagt bevorzuge ich die Verwendung einer Skriptsprache mit einem Parser. In diesem Fall perlmit XML::Twig.

Es geht ungefähr so:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

sub compare_by_identity {
   my ( $first, $second ) = @_;
   foreach my $identity ( $first->get_xpath('//Identity') ) {
      my $id = $identity->first_child_text('Id');

      print $id, "\n";
      my $compare_to =
        $second->get_xpath( "//Identity/Id[string()=\"$id\"]/..", 0 );
      if ($compare_to) {
         print "Matching element found for ID $id\n";
         foreach my $element ( $identity->children ) {
            my $tag  = $element->tag;
            my $text = $element->text;
            if ( not $element->text eq $compare_to->first_child_text($tag) ) {
               print "$id, $tag has value $text which doesn't match: ",
                 $compare_to->first_child_text($tag), "\n";
            }
         }
      }
      else {
         print "No matching element for Id $id\n";
      }
   }
}

my $first_file  = XML::Twig->new->parsefile('test1.xml');
my $second_file = XML::Twig->new->parsefile('test2.xml');

compare_by_identity( $first_file,  $second_file );
compare_by_identity( $second_file, $first_file );

Ich vergleiche explizit jeweils ein 'Identity'-Element und überprüfe, ob alle Felder in einem in dem anderen mit demselben Wert vorhanden sind.

Und dann kehren Sie das um, weil die zweite Datei möglicherweise zusätzliche Einträge enthält.

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.