Can perl's XML::SemanticDiff be shoehorned into order agnostic comparisons of two XML files?

Viewed 59

Hi: I'm trying to compare two XML files in perl and was hoping to do this using something that's alreay been invented. The most promising candidate I've found is XML::SemanticDiff. But it seems to be order sensitive when looking for diffs. Case in point, here's my perl script...

#!/usr/bin/env perl
use strict;
use XML::SemanticDiff;

my $diff = XML::SemanticDiff->new();

my $file1 = "xml1.xml";
my $file2 = "xml2.xml";

foreach my $change ($diff->compare($file1, $file2)) {
    print "$change->{message} in context $change->{context}\n";
}

exit;

And here are xml1.xml and xml2.xml ...

xml1.xml

<forest name="sterling">
  <species name="oak">
    <number value="10000"> </number>
    <avg_age value="200"> </avg_age>
    <type name="deciduous"> </type>
  </species>
  <species name="pine">
    <number value="15000"> </number>
    <avg_age value="180"> </avg_age>
    <type name="coniferous"> </type>
  </species>
</forest>

xml2.xml

<forest name="sterling"> 
  <species name="pine">
    <number value="15000"> </number>
    <avg_age value="180"> </avg_age>
    <type name="coniferous"> </type>
  </species>
  <species name="oak">
    <number value="10000"> </number>
    <avg_age value="200"> </avg_age>
    <type name="deciduous"> </type>
  </species>
</forest>

The content is the same but the order of the trees is swapped between the two. The perl script returns...

Attribute 'name' has different value in element 'species'. in context /forest[1]/species[1]
Attribute 'value' has different value in element 'avg_age'. in context
/forest[1]/species[1]/avg_age[1]
Attribute 'value' has different value in element 'number'. in context 
/forest[1]/species[1]/number[1]
Attribute 'name' has different value in element 'type'. in context 
/forest[1]/species[1]/type[1]
Attribute 'name' has different value in element 'species'. in context /forest[1]/species[2]
Attribute 'value' has different value in element 'avg_age'. in context 
/forest[1]/species[2]/avg_age[1]
Attribute 'value' has different value in element 'number'. in context 
/forest[1]/species[2]/number[1]
Attribute 'name' has different value in element 'type'. in context 
/forest[1]/species[2]/type[1]

And of course if the order of the species is the same, it returns nothing.

Is there a way to make this order agnostic, or is there a different pm that can do what I want?
Also, this has to be able to identify elements found in one of the xml files but missing in the other.

I'm open to non-perl solutions if there are any.

Thanks !

1 Answers

Consider sorting your xml files by attribute before running the compare. I found a project that lets you do that here. It shouldn't be too hard to do with XML::LibXML if you need an automated solution.

I found a similar question on SuperUser.

Related