Comment puis-je diff deux fichiers XML?

75

Sous Linux, comment générer un diff entre deux fichiers XML?

Idéalement, j'aimerais pouvoir le configurer sur certaines choses strictes ou desserrer certaines choses, telles que les espaces ou l'ordre des attributs.

Je veillerai souvent à ce que les fichiers soient fonctionnellement identiques, mais les diffs par eux-mêmes seraient gênants à utiliser, surtout si le fichier XML ne comporte pas beaucoup de sauts de ligne.

Par exemple, ce qui suit devrait vraiment me convenir:

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

<tag att2="two" att1="one">
  content
</tag>
Qedi
la source

Réponses:

86

Une approche consisterait tout d'abord à convertir les deux fichiers XML en XML Canonical et à comparer les résultats à l'aide de diff. Par exemple, xmllint peut être utilisé pour canoniser XML.

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

Ou comme un one-liner.

$ diff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)
Jukka Matilainen
la source
1
Jamais su sur le commutateur --c14n dans xmllint. C'est pratique.
Qedi
18
Vous pouvez aussi le faire en une lignevimdiff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)
Nathan Villaescusa,
et xmllint sont livrés avec OS X
ClintM
10
Au cas où cela ne serait pas évident, c14n est une abréviation de canonicalization .
Brandin
3
Il est préférable d’exécuter une étape supplémentaire avant le formatage diff des deux XML (xmllint --format). Parce que j'ai remarqué que sans cette étape, diff montre plus de différences que nécessaire.
ka3ak
23

La réponse de Jukka ne fonctionnait pas pour moi, mais elle renvoyait au code XML canonique. Ni --c14n ni --c14n11 ne trièrent les attributs, mais j’ai trouvé que le commutateur --exc-c14n triait les attributs. --exc-c14n ne figure pas dans la page de manuel, mais est décrit sur la ligne de commande comme étant "format canonique exclusif du 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)

Avertissement --exc-c14n supprime l'en-tête xml alors que --c14n ajoute l'en-tête xml s'il n'y est pas.

rjt
la source
18

J'ai essayé d'utiliser la réponse de @Jukka Matilainen, mais j'avais des problèmes d'espace blanc (l'un des fichiers était une énorme doublure). L'utilisation --formataide à ignorer les différences d'espaces.

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

Remarque: Utilisez la vimdiffcommande pour comparer côte à côte les fichiers XML.

GuruM
la source
Dans mon cas, a two.xmlété généré one.xmlpar un script. Je devais donc simplement vérifier ce qui était ajouté / supprimé par le script.
GuruM
1
C'était l'option dont j'avais besoin. Soi-disant, la version la plus canonique peut être obtenue en combinant --formatavec --exc-c14n; sera probablement encore plus lent à traiter :(
ᴠɪɴᴄᴇɴᴛ
Cela fait longtemps que je n’ai pas répondu, mais je me souviens très bien d’avoir utilisé le drapeau --exc-c14n. Cependant, la sortie avec / sans le drapeau ne montre aucune différence, alors arrêtez de l'utiliser. La suppression d’indicateurs inutiles / non utilisés peut accélérer le processus.
Gourou
5
L' --exc-c14noption spécifie le tri des attributs. Dans vos fichiers spécifiques, les attributs étaient probablement déjà triés, mais le conseil général serait d'utiliser la combinaison --format --exc-c14n.
ᴠɪɴᴄᴇɴᴛ
6

Diffxml obtient la fonctionnalité de base correcte, bien qu'elle ne semble pas offrir beaucoup d'options de configuration.

Edit: Project Diffxml a été migré vers GitHub depuis 2013.

dsolimano
la source
Ce n'est pas encore tout à fait là, mais au moins ça semble prometteur.
Qedi
pas utile pour les gros fichiers cependant, est mort après avoir mangé 40 Go (RAM + SWAP) en comparant deux fichiers ~ 20k lignes chacun
Grzegorz
noter que le projet semble être mort, avec la dernière mise à jour en 2013
Mateusz Konieczny
4

Si vous souhaitez également ignorer l'ordre des éléments enfants, j'ai écrit un outil python simple appelé xmldiffs:

Comparez deux fichiers XML en ignorant l'ordre des éléments et des attributs.

Usage: xmldiffs [OPTION] FILE1 FILE2

Toutes les options supplémentaires sont transmises à la diffcommande.

Obtenez-le à l' adresse https://github.com/joh/xmldiffs

joh
la source
1

Mon script Python xdiff.py pour la comparaison de fichiers XML ignore les différences d'espaces ou d'ordre d'attributs (contrairement à l'ordre des éléments).

Pour comparer deux fichiers 1.xmlet 2.xmlexécuter le script, procédez comme suit:

xdiff.py 1.xml 2.xml

Dans l'exemple du PO, il ne produirait rien et renverrait le statut de sortie 0(sans différences structurelles ou textuelles).

Dans les cas où 1.xmlet 2.xmldiffère structurellement, il imite la sortie unifiée du diff GNU et renvoie le statut de sortie 1. Il existe diverses options pour contrôler la sortie, telles que la -asortie de tout le contexte, la -nsortie sans contexte et la -qsuppression complète de la sortie (tout en retournant le statut de sortie).

Andreas Nolda
la source
0

J'utilise Beyond Compare pour comparer tous les types de fichiers texte. Ils produisent des versions pour Windows et Linux.

Alan
la source
1
Les comparaisons de texte en clair indiqueraient que les deux lignes sont différentes, alors que le PO souhaite qu'elles soient rapportées de la même manière.
ChrisF
4
c'est-à-dire comparer Canoniquement le XML.
Chris W. Rea
1
Beyond Compare craint vraiment pour ça. Il semble simplement ne pas être au courant des éléments XML et faire surtout de la comparaison de texte.
Rob K
Beyond Compare a un plugin XML mais je n'ai jamais réussi à l'installer correctement, alors ... Nyeah ... Je suis venu sur cette page et je suis devenu plus sage ...
Erk
-1

Notre SD Smart Differencer compare les documents en fonction de la structure et non de la présentation réelle.

Il y a un Smart Differencer XML. Pour XML, cela signifie un ordre de correspondance des balises et du contenu. Il convient de noter que la chaîne de texte dans le fragment spécifique que vous avez indiqué était différente. Actuellement, il ne comprend pas la notion XML d'attributs de balises indiquant si les espaces sont normalisés ou significatifs.

Ira Baxter
la source
1
Dans votre profil SO, vous fournissez une divulgation complète de votre employeur; J'aurais aussi préféré une brève clause de non-responsabilité dans votre réponse :) En passant, j'ai essayé de télécharger une copie d'évaluation, mais le formulaire de demande est suffisamment "intelligent" (via JS) pour désactiver la combinaison XML avec Smart Differencer (également ce dernier). en combinaison avec Python, bien que possible selon la page du produit SD)?
ᴠɪɴᴄᴇɴᴛ
1
Ah Merci pour le rappel. Ceci est une réponse d'un temps avant qu'il y ait eu une politique claire de SO à ce sujet. Je révise la réponse pour signaler la relation dans la réponse conforme à la politique SO.
Ira Baxter
Je vais vérifier la page de téléchargement; tous nos produits vivants ne font pas partie de cette liste. Oui, ceux-ci existent.
Ira Baxter
J'ai vérifié la page de téléchargement. Oui, le différenceur intelligent XML n'est pas là. Je demanderai aux gars de l'arrière-salle de réparer cela; devrait être là dans 1-2 semaines au plus (ils ont un arriéré, n'est-ce pas?) Dans l'intervalle, si vous voulez l'essayer, envoyez un email (voir bio).
Ira Baxter
1
La page liée ne contient pas le mot "XML".
Mateusz Konieczny
-1

Je ne suis pas sûr que la dépendance d'un outil en ligne compte comme une solution, mais j'ai obtenu de bons résultats avec cet outil de comparaison XML en ligne . Cela fonctionne simplement.

RayLuo
la source