Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XML

XML Comparer Library in C#

4.92/5 (4 votes)
18 Oct 2015CPOL2 min read 24K   306  
XML Comparer library in C#

Introduction

This is a small library I have developed to help me write utilities which involve comparison of XML files.

Background

In my various jobs in the past, I had to write utilities to compare / transform / generate documentation of configuration files which were normal app.config files (i.e. XML). For this, I had to start with implementation of some sort of XML comparer everytime and I could not publish that code due to the policies of the employers.

This time, I decided to write the code once, make it open source and use it in future.

I tried looking for any existing implementations and the one that came closest to be the final choice was the XML Diff & Patch library from Microsoft. But it failed on the very first sample of XML files I threw at it.

Using the Code

The code is available on github here.

Using the code is as simple as:

  1. Implementing IXmlCompareHandler interface (defined in the library). The interface is defined as follows:
    C#
    public interface IXmlCompareHandler
    {
        void ElementAdded(ElementAddedEventArgs e);
        void ElementRemoved(ElementRemovedEventArgs e);
        void ElementChanged(ElementChangedEventArgs e);
        void AttributeAdded(AttributeAddedEventArgs e);
        void AttributeRemoved(AttributeRemovedEventArgs e);
        void AttributeChanged(AttributeChangedEventArgs e);
    }
    
  2. Using the class Comparer (defined in the library).

    The sample console application included in the git repository shows how easy it is. The following code is taken from the same console application:

    C#
    class Program
    {
            static void Main(string[] args)
            {
                try
                {
                    var file1 = @".\TestFiles\a1.config";
                    var file2 = @".\TestFiles\a2.config";
                    var handler = new TestXmlCompareHandler();
                    using (var comparer = new Comparer(handler))
                    {
                        comparer.Compare(file1, file2, handler);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("ERROR: " + ex);
                }
                Console.Write("Press RETURN to close...");
                Console.ReadLine();
            }
    }

The sample files used in the above example are also the git repository in github. The adapted version of those files is shown below:

File 1

XML
<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="initialdatafile" value="db-import.xml"/>
    <add key="migratedatafile" value="db-migrate2.xml" />
  </appSettings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
  </startup>
</configuration>

File 2

XML
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="initialdatafile" value="db-import.xml" />
    <add key="migratedatafile" value="db-migrate.xml" />
  </appSettings>
</configuration> 

On running the console application, the result is:

<>A: /configuration/appSettings/add[@key="migratedatafile"]/@value
     o: 5       : db-migrate2.xml
     n: 5       : db-migrate.xml

-E: 7      : /configuration/startup
             : <startup>   <supportedRuntime version="v4.0" 
             sku=".NETFramework,Version=v4.5.1" /> </startup>

As you can see, it shows the difference in attributes (marked by "<>A") and also shows that one element was removed (marked by "--E"). Note that this output was generated by the TestXmlCompareHandler (the class that implements interface "IXmlCompareHandler".

Your implementation of "IXmlCompareHandler" can do anything you want. Part of the code that produced the above output is:

C#
public void ElementChanged(ElementChangedEventArgs e)
{
    Console.WriteLine("<>E: {0}", e.XPath);
    Console.WriteLine("  o: {0,-8}:             {1}", e.LeftLineNumber, e.LeftElement.Value);
    Console.WriteLine("  n: {0,-8}:             {1}", e.RightLineNumber, e.RightElement.Value);
    Console.WriteLine();
}

Points of Interest

The XML comparer class treats XML files as XML documents and not some text files. So order of the elements does not matter.

Roadmap

  1. Addition of "Patcher" class which can be used for transforming XML files by poking in values for attributes / elements or even full blown elements
  2. Create NuGet packages

History

  • Initial release
  • Link to code in the form of zip file for easier download

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)