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:
- Implementing
IXmlCompareHandler
interface (defined in the library). The interface is defined as follows:
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);
}
- 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:
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
="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
="1.0"="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:
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
- Addition of "
Patcher
" class which can be used for transforming XML files by poking in values for attributes / elements or even full blown elements - Create NuGet packages
History
- Initial release
- Link to code in the form of zip file for easier download