Como posso diferenciar dois arquivos XML?


75

No Linux, como eu poderia gerar uma diferença entre dois arquivos XML?

Idealmente, eu gostaria de poder configurá-lo para algumas coisas estritas ou afrouxar algumas coisas, como espaço em branco ou ordem de atributos.

Eu sempre me importarei que os arquivos sejam funcionalmente iguais, mas o diff por si só seria irritante de usar, principalmente se o arquivo XML não tiver muitas quebras de linha.

Por exemplo, o seguinte realmente deve ser bom para mim:

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

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

Respostas:


86

Uma abordagem seria primeiro transformar os dois arquivos XML em XML canônico e comparar os resultados usando diff. Por exemplo, xmllint pode ser usado para canonizar XML.

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

Ou como uma linha.

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

11
Nunca soube da opção --c14n no xmllint. Isso é útil.
qedi

18
Você pode fazê-lo em uma linha tambémvimdiff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)
Nathan Villaescusa

e navios xmllint com OS X
ClintM

10
Caso isso não fosse óbvio, c14n é uma abreviação de canonicalização .
Brandin

3
É melhor executar uma etapa adicional antes da formatação diferencial de ambos os XMLs (xmllint --format). Porque notei que, sem esta etapa, o diff mostra mais diferenças do que o necessário.
ka3ak

23

A resposta de Jukka não funcionou para mim, mas apontou para XML canônico. Nem --c14n nem --c14n11 classificaram os atributos, mas eu achei a opção --exc-c14n classificando os atributos. --exc-c14n não está listado na página de manual, mas é descrito na linha de comandos como "formato canônico exclusivo do W3C".

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

Aviso --exc-c14n retira o cabeçalho xml, enquanto o --c14n precede o cabeçalho xml, se não estiver lá.


18

Tentou usar a resposta de @Jukka Matilainen, mas teve problemas com espaço em branco (um dos arquivos era um grande número de linhas). O uso de --formatajuda para ignorar as diferenças de espaço em branco.

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

Nota: Use o vimdiffcomando para comparar lado a lado os xmls.


No meu caso, two.xmlfoi gerado a partir one.xmlde um script. Então, eu só precisava verificar o que foi adicionado / removido pelo script.
GuruM 8/08

11
Essa era a opção que eu precisava. Supostamente a versão mais canônica pode ser obtida combinando-se --formatcom --exc-c14n; provavelmente ainda será mais lento para processar :(
>

Já faz algum tempo desde que escrevi a resposta, mas me lembro levemente do uso da bandeira --exc-c14n. No entanto, diferenciar a saída com / sem o sinalizador não mostrou diferenças, apenas parou de usá-lo. Soltar sinalizadores desnecessários / não utilizados pode tornar o processo mais rápido.
GuruM

5
A --exc-c14nopção especifica a classificação dos atributos. Nos seus arquivos específicos, os atributos provavelmente já foram classificados, mas o conselho geral seria usar a combinação --format --exc-c14n.
ᴠɪɴᴄᴇɴᴛ

6

O Diffxml corrige a funcionalidade básica, embora não pareça oferecer muitas opções de configuração.

Editar: o projeto Diffxml foi migrado para o GitHub desde 2013.


Ainda não chegou lá, mas parece promissor, pelo menos.
qedi

não é útil para arquivos grandes, porém, morreu depois de comer 40GB (RAM + SWAP) ao comparar dois arquivos ~ 20k linhas cada
Grzegorz

notar que o projeto parece estar morto, com a última atualização em 2013
Mateusz Konieczny

4

Se você também deseja ignorar a ordem dos elementos filhos, escrevi uma ferramenta python simples para isso chamada xmldiffs:

Compare dois arquivos XML, ignorando a ordem dos elementos e atributos.

Uso: xmldiffs [OPTION] FILE1 FILE2

Quaisquer opções extras são passadas para o diffcomando.

Obtê-lo em https://github.com/joh/xmldiffs


1

Meu script Python xdiff.py para comparar arquivos XML ignora diferenças no espaço em branco ou na ordem dos atributos (em contraste com a ordem dos elementos).

Para comparar dois arquivos 1.xmle 2.xml, execute o script da seguinte maneira:

xdiff.py 1.xml 2.xml

No exemplo do OP, ele não produziria nada e retornaria o status de saída 0(sem diferenças estruturais ou textuais).

Nos casos em que 1.xmle 2.xmldiferem estruturalmente, ele imita a saída unificada do diff GNU e retorna o status de saída 1. Existem várias opções para controlar a saída, como -aa saída de todo o contexto, -na saída de nenhum contexto e -qa supressão total da saída (enquanto ainda retorna o status de saída).


0

Eu uso o Beyond Compare para comparar todos os tipos de arquivos baseados em texto. Eles produzem versões para Windows e Linux.


11
As comparações em texto simples diriam que as duas linhas diferem, enquanto o OP deseja que elas sejam relatadas da mesma forma.
7119 ChrisF

4
ou seja, comparar canonicamente o XML.
9119 Chris W. Rea

11
Beyond Compare realmente é péssimo para isso. Parece apenas não estar ciente dos elementos XML e fazer principalmente apenas a comparação de texto.
Rob K

O Beyond Compare possui um plug-in XML, mas eu nunca fui capaz de instalá-lo corretamente, então ... Nyeah ... Eu vim a esta página e fiquei mais sábio ...
Erk 14/03

-1

Nosso SD Smart Differencer compara documentos com base na estrutura e não no layout real.

Existe um XML Smart Differencer. Para XML, isso significa ordem de correspondência de tags e conteúdo. Observe que a sequência de texto no fragmento específico que você indicou era diferente. Atualmente, ele não entende a noção XML de atributos de marca, indicando se o espaço em branco é normalizado versus significativo.


11
No seu perfil de SO, você fornece divulgação completa sobre seu empregador; Eu também teria preferido um pequeno aviso de isenção na sua resposta :) BTW, tentei fazer o download de uma cópia de avaliação, mas o formulário de solicitação é 'inteligente' (via JS) o suficiente para desativar a combinação XML com o Smart Differencer (também o último em combinação com Python, embora possível, de acordo com a página do produto SD)?
ᴠɪɴᴄᴇɴᴛ

11
Ah Obrigado pela lembrança. Esta é uma resposta de um tempo antes de haver uma política clara de SO sobre isso. Estou revisando a resposta para sinalizar o relacionamento na resposta compatível com a política de SO.
Ira Baxter

Vou verificar a página de download; nem todos os nossos produtos ao vivo fazem parte dessa lista. Sim, existem.
Ira Baxter

Eu verifiquei a página de download. Sim, o diferencial inteligente XML não está lá. Vou mandar os caras da sala trabalharem para consertar isso; deve ocorrer em uma ou duas semanas, no máximo (eles têm uma lista de pendências, não temos?) Enquanto isso, se você quiser experimentar, envie um email (consulte a biografia).
Ira Baxter

11
A página vinculada não possui a palavra "XML".
Mateusz Konieczny

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.