如何区分两个XML文件?


74

在Linux上,如何在两个XML文件之间生成差异?

理想情况下,我希望能够将其配置为严格的某些内容,或者放宽某些内容,例如空格或属性顺序。

我经常会担心文件在功能上是相同的,但是仅使用diff会令人讨厌,尤其是在XML文件没有很多换行符的情况下。

例如,以下对我来说真的应该可以:

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

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

Answers:


85

一种方法是首先将两个XML文件都转换为Canonical XML,然后使用进行比较diff。例如,xmllint可用于规范化XML。

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

或作为单线。

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

1
从不知道xmllint中的--c14n开关。那很方便。
qedi

18
您也可以在一行中完成它vimdiff <(xmllint --c14n one.xml) <(xmllint --c14n two.xml)
Nathan Villaescusa

和xmllint随OS X一起发布
ClintM '16

10
如果不太明显,则c14n是规范化的缩写。
布兰丁

3
最好在对两种XML进行差异格式化(xmllint --format)之前执行额外的步骤。因为我已经注意到,没有这一步,差异会显示出不必要的差异。
ka3ak '16

23

Jukka的答案对我不起作用,但确实指向Canonical XML。--c14n--c14n11都没有对属性进行排序,但是我确实找到了--exc-c14n开关对属性进行了排序。 --exc-c14n没有在手册页中列出,但是在命令行上以“ 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)

警告--exc-c14n会 删除xml标头,而--c14n如果不存在,则会在xml标头前添加。


18

尝试使用@Jukka Matilainen的答案,但空格存在问题(其中一个文件是一个很大的单行)。使用--format有助于跳过空格差异。

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

注意:使用vimdiff命令来并排比较xml。


就我而言,two.xmlone.xml由脚本生成的。因此,我只需要检查脚本添加/删除的内容。
GuruM

1
这是我需要的选项。可以通过--format与结合获得最规范的版本--exc-c14n。可能会是慢还是处理:(
ᴠɪɴᴄᴇɴᴛ

自从我写出答案以来已经有一段时间了,但是我微弱地记得使用--exc-c14n标志。但是,对带有/不带有标志的输出进行差异显示没有区别,因此仅停止使用它。删除不必要/未使用的标志可能会使过程更快。
GuruM

5
--exc-c14n选项指定属性的排序。在您的特定文件中,属性可能已经排序,但是一般建议是使用组合--format --exc-c14n
ᴠɪɴᴄᴇɴᴛ

6

尽管Diffxml似乎没有提供许多配置选项,但Diffxml的基本功能正确无误。

编辑:自2013年以来,Diffxml项目已迁移到GitHub。


它还不存在,但至少看起来很有希望。
qedi

虽然不适用于大文件,但是在比较两个文件(每行约20k行)时吃掉40GB(RAM + SWAP)后就死了
Grzegorz

请注意,该项目似乎已经死了,最后更新时间是2013年
Mateusz Konieczny

4

如果您还希望忽略子元素的顺序,我为此编写了一个简单的python工具xmldiffs

比较两个XML文件,忽略元素和属性的顺序。

用法: xmldiffs [OPTION] FILE1 FILE2

任何其他选项都将传递给diff命令。

https://github.com/joh/xmldiffs上获取


1

我的用于比较XML文件的Python脚本xdiff.py忽略了空格或属性顺序的差异(与元素顺序相反)。

为了比较两个文件1.xml2.xml,您可以按如下运行脚本:

xdiff.py 1.xml 2.xml

在OP的示例中,它将不输出任何内容并返回退出状态0(无结构或文本差异)。

1.xml2.xml结构上不同的情况下,它会模仿GNU diff的统一输出并返回退出状态1。有多种选项可用于控制输出,例如-a用于输出所有上下文,-n不输出上下文以及-q完全禁止输出(同时仍返回退出状态)。


0

我使用“ 超越比较”来比较所有类型的基于文本的文件。他们为Windows和Linux生产版本。


1
纯文本比较将表明这两行是不同的,而OP希望将它们报告为相同。
ChrisF,2009年

4
规范地比较 XML。
克里斯·瑞

1
超越比较真的很烂。似乎只是不了解XML元素,而只是做文本比较。
罗布K

Beyond Compare有一个XML插件,但我始终无法正确安装它,所以……Nyeah……我来到此页面,变得更明智了……
Erk

-1

我们的SD智能差异器根据结构而不是实际布局比较文档。

有一个XML智能差异器。对于XML,这意味着标签和内容的匹配顺序。应该注意的是,您指定的特定片段中的文本字符串是不同的。目前,它不了解标记属性的XML概念,该属性指示空白是否已规范化还是有效。


1
在您的个人资料中,您提供了有关您雇主的完整披露;我也希望在您的答案中使用简短的免责声明:)顺便说一句,我尝试下载评估副本,但请求表“很聪明”(通过JS)足以禁用XML与Smart Differencer(也包括后者)的组合与Python结合使用,尽管根据SD产品页面可能)?
ᴠɪɴᴄᴇɴᴛ

1
啊。感谢您的提醒。这是在制定明确的SO政策之前的一个答案。我正在修改答案,以表明符合SO策略的答案中的关系。
Ira Baxter

我将检查下载页面;并非我们所有的实时产品都包含在该列表中。是的,这些存在。
Ira Baxter 2014年

我检查了下载页面。是的,XML智能差异器不存在。我要让后台人员来解决这个问题;最多应该在1-2周内到达(他们有积压的订单,不是吗?)同时,如果您想尝试,请发送电子邮件(请参阅简历)。
艾拉·巴克斯特

1
链接的页面中没有单词“ XML”。
Mateusz Konieczny

-1

不确定在线工具的依赖性是否可以作为解决方案,但是,对于它的价值,我在此在线XML比较工具中获得了不错的成绩。它简单地工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.