¿Cómo comparar dos archivos xml que tienen los mismos datos en diferentes líneas?

9

Tengo dos archivos con los mismos datos pero en líneas diferentes.

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

Archivo 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 uso el diff file1 file2comando obtengo la siguiente respuesta:

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>

Pero no necesito diferenciar, porque estos archivos tienen los mismos datos en diferentes líneas.

usuario32026
fuente
Al ordenarlos en línea y compararlos, puede verificar si no son iguales . Por supuesto, igual después de la clasificación no significa que sean realmente iguales, ya que la clasificación destruye la sintaxis XML.
jofel
No se como resolverlo. difieren por orden en el archivo 1 a luego b y en el archivo 2 b luego a. puede exponer la pregunta con diff -y -B -Z -b --strip-trailing-cr
file1 file2
2
Podría intentarlo xmldiff, pero creo que aún notará que el orden cambia, ya que el orden es relevante en XML genérico. Creo que su mejor enfoque es usar un analizador y generador XML para colocar cada archivo en un orden y formato canónicos, luego use xmldiffo diff. Un trabajo para su lenguaje de secuencias de comandos favorito (Perl, Ruby, Python, etc.).
derobert

Respuestas:

6

Puede lograr lo que desea con la ayuda de un pequeño script de Python (necesitará Python instalado, así como el lxmlkit de herramientas).

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)

Este script clasifica los elementos de primer nivel bajo la raíz del documento XML por el contenido de un elemento de segundo nivel, enviando el resultado a stdout. Se llama así:

$ python tagsort.py filename tag

Una vez que tenga eso, puede usar la sustitución del proceso para obtener un diferencial basado en su salida (he agregado un elemento y cambiado otro en sus archivos de ejemplo para mostrar un resultado no vacío):

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

fuente
3

Tuve un problema similar y finalmente encontré: /superuser/79920/how-can-i-diff-two-xml-files

Esa publicación sugiere hacer una ordenación xml canónica y luego hacer una diferencia. Lo siguiente debería funcionar para usted si está en Linux, Mac o si tiene Windows algo como Cygwin instalado:

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

Está etiquetado como shell, pero honestamente prefiero usar un lenguaje de script con un analizador sintáctico. En este caso perlcon XML::Twig.

Es algo parecido a esto:

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

Estoy comparando explícitamente un elemento de 'Identidad' a la vez y verificando que todos los campos en uno existan en el otro, con el mismo valor.

Y luego revertir eso, porque el segundo archivo podría tener entradas adicionales.

Sobrique
fuente