28

I'm looking for a Windows based diff tool that shows me the differences between two XML files, but does this tree-based, not line-based.
I.e. if a section has moved to a totally different place in the file it should not report differences.
These two files should be reported as 'the same':

<soapenv:Body>
  <mes:GetItem>
    <mes:ItemShape>
      <typ:BaseShape>IdOnly</typ:BaseShape>
      <typ:BodyType>Text</typ:BodyType>
      <typ:AdditionalProperties>
        <typ:FieldURI FieldURI="item:Subject" />
        <typ:FieldURI FieldURI="item:Categories" />
      </typ:AdditionalProperties>
    </mes:ItemShape>
    <mes:ItemIds>
      <typ:ItemId Id="AAMYAAA="/>
    </mes:ItemIds>
  </mes:GetItem>
</soapenv:Body>


<soapenv:Body>
  <mes:GetItem>
    <mes:ItemIds>
      <typ:ItemId Id="AAMYAAA="/>
    </mes:ItemIds>
    <mes:ItemShape>
      <typ:BodyType>Text</typ:BodyType>
      <typ:BaseShape>IdOnly</typ:BaseShape>
      <typ:AdditionalProperties>
        <typ:FieldURI FieldURI="item:Categories" />
        <typ:FieldURI FieldURI="item:Subject" />
      </typ:AdditionalProperties>
    </mes:ItemShape>
  </mes:GetItem>
</soapenv:Body>

And of course, all differences should be marked, preferably in a side-by-side view with indicators or lines connecting the sections that differ.

Free would be nice.
Optionaly ignoring name spaces would be nice.

  • 1
    Possible duplicate of Free XML Compare Tool – rrirower Mar 20 '15 at 19:11
  • 3
    @rrirower yeah but it got closed there :/ Stack Exchange has this tendency of closing instead of migrating. – Franck Dernoncourt Mar 21 '15 at 2:19
  • Jan, have you tried the most common diff programs on Windows, such as WinMerge2011, to see if they have an option for that functionality? (Note that WinMerge2011 has many updates since the last update of regular WinMerge, even if the name implies the opposite.) – RockPaperLizard Mar 21 '15 at 23:56
  • 1
    "reported as 'the same'" ... These XML files are the "same" only true if you insist that the order of some tags is irrelevant. For some folks, the order does matter. You need a schema or some other signal to indicate which case, for which tags. – Ira Baxter Jun 24 '15 at 18:04
  • 1
    @Mast My current work no longer needs this, so I have this on the back burner. Still plan to revisit this post though, when I can make some time. – Jan Doggen Jul 23 '18 at 7:22
8

Technically, XMLs are different

  • if they have whitespaces or not
  • if the order is different
  • if they have comments or not
  • if they have processing instructions or not
  • if their encoding is different
  • if their namespaces are different

but of course you can decide to ignore that or not, based on the semantic information an XML does not have.

Microsoft has developed the XML Diff and Patch tool for this purpose and you can integrate it in your own applications.

Note: the tool installs as "SQLXML Bulkload in .NET Code Sample" and comes with a Visual Studio solution XmlDiffView.sln that you need to compile yourself. Some basic programming knowledge in C# and Visual Studio Community Edition should be ok.

However, as mentioned in one of the answers on Stack Overflow, it has been compiled and made available on Bitbucket.

After that it comes with a UI that let's you choose the various XML comparison options:

XmlDiff UI

When I apply it to the 2 XMLs of your questions, it throws an exception. That is because of the namespaces which are not defined. After removing the namespaces, it says:

Files identical for the given options

  • 1
    Thanks. I have upvoted this answer but not marked it as the correct one. Reason: the interface of the results window of the GUI tool is horrible: when comparing two large XML files, the diff window is approx 3000 pixels wide, contains all identical XML, and has no scrollbars. Then try to find the differences between two 55 MB files ;-( I'm not a Cx programmer so I can't adapt the program. – Jan Doggen Apr 3 '17 at 12:16
  • @JanDoggen: yes, I agree, it's very developer-oriented. It can hardly be used without programming skills. – Thomas Weller Apr 3 '17 at 12:23
  • @JanDoggen The scrollbar is a tiny sliver only a couple pixels wide at the right edge of the window. I agree the output isn't very pretty, but it is still a useful tool. – Suncat2000 Aug 3 '17 at 13:10
  • @ThomasWeller +1 for the link to BitBucket. I compiled, but had no luck, getting the original source working. – Suncat2000 Aug 3 '17 at 13:12
6

Focusing on the part that moved sections should be reported as no difference made me think of http://semanticmerge.com/, which doesn't compare XML-files, but C# and C code. And as it understand those languages it is able to display if code has moved and not changed.

This leads to an alternative approach for this question: Could it be possible to translate the XML into C# classes, and then do a semantic merge on the resulting code?

One possible approach, if this tool is not written already, could be to translate each and every element to classes, and each attribute (and body texts) to a string property within that class. If you want to ignore namespaces, then let your translator remove them in the translation process.

I translated the XML example given as proof of concept and got the following:

class soapenv__Body {
  class mes__GetItem {
    class mes__ItemShape {
      class typ__BaseShape {
          string body="IdOnly";
      }
      class typ__BodyType {
          string body="Textus";
      }
      class typ__AdditionalProperties {
        class typ__FieldURI  {
            string FieldURI="item:Subject";
        }
        class typ__FieldURI  {
            string FieldURI="item:Categories"; 
        }
      }
    }
    class mes__ItemIds {
      class typ__ItemId {
          string Id="AAMYAAA=";
      }
    }
  }
}

Then I switched the mes:ItemIds and mes:ItemShape and changed the text to Textus. Compared the following two files in Semantic Merge and got the following image:

Semantic Merge screenshot

In this image one can see the move, indicated by the M icon, and the change in text indicated by the C icon. Lines indicates where the different parts have moved/changed, and it possible to actually see the differences if they exist.

Note that Semantic Merge even though understanding C# code, isn't to strict on the identical class names of typ__FieldURI, which could be a nice features as XML can contain multiple nodes with the same name.

Summa summarum: Semantic Merge can correctly identify the XML as identical (or not) even though elements move, if you can convert the XML into a C# class structure.

  • Just for the fun of it, I tried moving the typ:FieldUri elements, and Semantic Merge correctly identified them as moved. So the order is correctly detected, and you can track order of attributes if so wanted. – holroy Jun 26 '15 at 21:36
2

Technically those aren't the same (at least in xml), order does matter unless that is made explicit in the schema.

A combination of xmlstarlet and normal line-based utilities can make the problem much more tractable.

The following only compares the structure, but could be extended to look at the attributes,their values, and text

xmlstarlet el snippet1-with-namespaces.xml | sort > structure1.txt

xmlstarlet el snippet2-with-namespaces.xml | sort > structure2.txt

diff structure.txt structure2.txt

After running this on your snippets the diff shows no differences but there was some error text about namespaces (which would be safe to ignore).

0

Currently I am trying to solve a quite similar problem for myself. Unfortunately I did not find any library thats suits my needs to produce a svg visualization of an xml comparison.

Therefore I started an open source library inspired by the X-Diff algorithm. So just for fun and in the hope to find someone supporting the XmlXdiff library. Till now it is not a bullet prove library and still under construction but here is the result for your example snippet:

enter image description here

Code producing this result:

    from XmlXdiff.XReport import DrawXmlDiff

    _xml1 = """<frame xmlns:soapenv="sn" xmlns:mes="meas" xmlns:typ="type">
    <soapenv:Body>
      <mes:GetItem>
        <mes:ItemShape>
          <typ:BaseShape>IdOnly</typ:BaseShape>
          <typ:BodyType>Text</typ:BodyType>
          <typ:AdditionalProperties>
            <typ:FieldURI FieldURI="item:Subject" />
            <typ:FieldURI FieldURI="item:Categories" />
          </typ:AdditionalProperties>
        </mes:ItemShape>
        <mes:ItemIds>
          <typ:ItemId Id="AAMYAAA="/>
        </mes:ItemIds>
      </mes:GetItem>
    </soapenv:Body>
    </frame>"""
    _xml2 = """<frame xmlns:soapenv="sn" xmlns:mes="meas" xmlns:typ="type">
    <soapenv:Body>
      <mes:GetItem>
        <mes:ItemIds>
          <typ:ItemId Id="AAMYAAA="/>
        </mes:ItemIds>
        <mes:ItemShape>
          <typ:BodyType>Text</typ:BodyType>
          <typ:BaseShape>IdOnly</typ:BaseShape>
          <typ:AdditionalProperties>
            <typ:FieldURI FieldURI="item:Categories" />
            <typ:FieldURI FieldURI="item:Subject" />
          </typ:AdditionalProperties>
        </mes:ItemShape>
      </mes:GetItem>
    </soapenv:Body>
    </frame>"""

    _path1 = '{}\\..\\..\\tests\\simple\\xml1.xml'.format(getPath())
    _path2 = '{}\\..\\..\\tests\\simple\\xml2.xml'.format(getPath())
    _out = '{}\\..\\..\\tests\\simple\\xdiff.svg'.format(getPath())

    with open(_path1, "w") as f:
        f.write(_xml1)

    with open(_path2, "w") as f:
        f.write(_xml2)

    x = DrawXmlDiff(_path1, _path2)
    x.draw()
    x.saveSvg(_out)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.