比较两个XML文件,无需关心元素和属性的顺序

时间:2016-11-22 07:08:29

标签: xml compare

我最近遇到了一个问题:我有两个XML文件,我需要检查它们是否与内容相同。两个文件都具有相同类型的元素节点,但顺序不同,并且节点的属性也相同。举个例子:

这是file1.xml

<Car name="Ferrari" speed="420">
    <Engine>V12</Engine>
    <Color name="Red"/>
</Car>
<Car name="Lamborghini" speed="380">
    <Engine>SV</Engine>
    <Color name="White"/>
</Car>

这是file2.xml

<Car speed="380" name="Lamborghini">
    <Color name="White"/>
    <Engine>SV</Engine>
</Car>
<Car speed="420" name="Ferrari">
    <Color name="Red"/>
    <Engine>V12</Engine>
</Car>

我需要比较这两个文件的东西,如果它们是“等于”则返回true,否则它会显示差异。 (在示例中,它必须返回true)

显然这是一个例子,我必须检查的文件里面有50.000+行元素。

我正在寻找的是一切:软件,使用的库,手动算法。

非常感谢。

1 个答案:

答案 0 :(得分:1)

首先,我将您的样本包装到<R> ... </R>以从中制作XML文档。

然后,我使用xsh将输入文件处理为元素的规范顺序:我按名称和@name属性对所有子元素进行了排序。

my $F1 := open file1.xml ;
my $F2 := open file2.xml ;
my $nodes = ( $F1//* | $F2//* ) ;
for my $element in { reverse @$nodes } {
    if ($element/*) {
        xmove &{ sort :k concat(name(), '|', @name) $element/* }
            append $element ;
    }
}

save :f file1.out.xml $F1 ;
save :f file2.out.xml $F2 ;

以相反的顺序走节点至关重要,否则排序将无法正常工作。

为了比较生成的XML,我使用了使用xmllint的旧xmldiff bash脚本:

#!/bin/bash

a=($@)
b=$#
f2=${a[$((--b))]}
f1=${a[$((--b))]}
diff "${a[@]:0:$b}" \
   <(xmllint --c14n "$f1" |xmllint --format -) \
   <(xmllint --c14n "$f2" |xmllint --format -)