comment comparer deux fichiers xml ayant les mêmes données sur des lignes différentes?

9

J'ai deux fichiers ont les mêmes données mais dans des lignes différentes.

Fichier 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>

Fichier 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>

Si j'utilise la diff file1 file2commande, je reçois ci-dessous la réponse:

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>

Mais je n'ai besoin de faire aucune différence, car ces fichiers ont les mêmes données sur des lignes différentes.

user32026
la source
En les triant en ligne et en les comparant, vous pouvez vérifier s'ils ne sont pas égaux . Bien sûr, égal après tri ne signifie pas qu'ils sont vraiment égaux car le tri détruit la syntaxe XML.
jofel
Je ne sais pas comment le résoudre. ils diffèrent par ordre dans le fichier 1 a puis b et dans le fichier 2 b puis a. vous pouvez exposer la question avec diff -y -B -Z -b --strip-trailing-cr file1
file2
2
Vous pouvez essayer xmldiff, mais je pense que vous remarquerez toujours que l'ordre change, car l'ordre est pertinent dans le XML générique. Je pense que votre meilleure approche est d'utiliser un analyseur et un générateur XML pour mettre chaque fichier dans un ordre et un format canoniques, puis utiliser xmldiffou diff. Un travail pour votre langage de script préféré (Perl, Ruby, Python, etc.).
derobert

Réponses:

6

Vous pouvez réaliser ce que vous voulez à l'aide d'un petit script Python (vous aurez besoin de Python installé, ainsi que de la lxmlboîte à outils).

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)

Ce script trie les éléments de premier niveau sous la racine du document XML en fonction du contenu d'un élément de second niveau, en envoyant le résultat à stdout. Cela s'appelle comme ceci:

$ python tagsort.py filename tag

Une fois que vous avez cela, vous pouvez utiliser la substitution de processus pour obtenir un diff basé sur sa sortie (j'ai ajouté un élément et changé un autre dans vos fichiers d'exemple pour afficher un résultat non vide):

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

la source
3

J'ai eu un problème similaire et j'ai finalement trouvé: /superuser/79920/how-can-i-diff-two-xml-files

Ce post suggère de faire un tri canonique xml puis de faire un diff. Les éléments suivants devraient fonctionner pour vous si vous êtes sous linux, mac ou si vous avez installé quelque chose comme cygwin:

$ xmllint --c14n File1.xml > 1.xml
$ xmllint --c14n File2.xml > 2.xml
$ diff 1.xml 2.xml
VenomFangs
la source
0

C'est un shell tagué, mais honnêtement, je préfère utiliser un langage de script avec un analyseur. Dans ce cas perlavec XML::Twig.

Ca fait plutot comme ca:

#!/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 );

Je compare explicitement un élément 'Identity' à la fois et vérifie que tous les champs de l'un existent dans l'autre, avec la même valeur.

Et puis inverser cela, car le deuxième fichier peut avoir des entrées supplémentaires.

Sobrique
la source