This project is read-only.

Xompare - XML comparator GUI utility

Contents

  1. Intro
  2. Installation
  3. Usage
  4. Command Line Interface
  5. XML comparison method used
  6. Xompare configuration
  7. Something about the source-library
  8. Credits

Intro

This is a utility to graphically view the differences between two given XML files. It can show what’s removed, what’s newly added, differences between elements and attributes and to easy navigate within a tree-representation of the XML files.

Xompare short intro
Xompare short intro

Installation

Make sure you have .NET 4.5 runtime framework installed.
If you have Windows 8 or newer, you have it. Otherwise - you can download it here.

Download the application (binary bundle), unzip and run 'Xompare.exe'.

Usage

Menu File/New File Comparison - and select the 'original' XML file and the 'target' XML file. Any XML content will do, regardless of the file's extension.
Another way to invoke XML comparison is by running the utility from command line, see CLI information below.
If the XML file chosen contains XML-invalid syntax, you will be notified, and no comparison will take place.

Command Line Interface

Running the utility from command line allows to specify commands for:
  1. Compare 2 XML files
  2. Get help on the available CLI syntax. Note that in menu Help/CLI syntax - you can find the syntax available for the CLI.
The CLI syntax is as follows:

filediff|files|f: Compares given XML files

/ofn /originalfilename : The original XML file name (String)
/ol /labelfororiginal : A label describing the original XML file (String)
/tfn /targetfilename : The target XML file name (String)
/tl /labelfortarget : A label describing the target XML file (String)

Global Parameters:

/h /help : Display this syntax information message (Boolean)
/debug : (Boolean)

XML comparison method used

It is important that you understand the way the comparison is done, since it is a bit different from a simple textual comparison. (I will be glad to read comments for improvements).
In order to determine if an XML element (element henceforth) or an XML attribute (attribute henceforth) was added, removed or changed, we need to define a key which identifies it. Let's refer to both elements and attributes as XML nodes, or simply nodes.
When a key of a node exists only in the original XML, we say that it was removed.
Similarly, when a key of a node exists only in the target XML, we say that it was added.
If the key exists on both sides of the comparison, then we can differentiate it, and if we find differences (like in element value, or attribute value) - then we say the nodes are different.
To determine how a node's key is built, lets look at the following parameters that when combined together may form a key to distinguish it from other nodes:
  1. The node's absolute path, including namespaces.
  2. The node's value (please see a remark below about an element's value).
  3. A combination of an element's attributes names and values (if the node is an element).
  4. The combination of the element's children keys (recursive definition). This parameter is not useful, since it renders the ability to differentiate between similar elements impossible. Suppose you have just an attribute change of value in one of the inner decedent elements of element X. This means, that the key of this ancestor X element will be different between the original and the target XMLs and so will be shown as 'removed/added' instead of changed.
A remark about an element's value: The value (property) of an element is defined to be any text written in it, which is not another definition of an attribute or element. On top of that, the value of an element concatenates to itself the values of its inner elements, recursively. This renders the use of the element's value property in the element key - useless, for the same reason stated above. Unless - the value of an element is determined only by the text written in it without the values of its children elements. This is the approach used here for the use of an element's value property within a node's key.

What's described above may be used as a general key:
  • For elements, we have a key composed of an absolute path, trimmed value and a combination of its attributes names and values.
  • For attributes, we have a key composed of an absolute path (including the attribute's name) and the parent element's key.
This allows us to differentiate easily between elements that have the same path and name (like in a collection).
But when such an element is changed only by one of its attributes - the comparison will show 'add/remove' instead of 'change'. For the comparator to know that this is a change, we need it to understand that there was a change, and for that we define a new type of key - the user key.
'User' - because the user defines it, and currently it is defined using the configuration file of the application found in the binary bundle. See also below about the configuration file.
The user key simply defines a name of an attribute, which if found in the element - is used for its values as the element's key (combined with the element's path).
The image above describes a situation where the attribute 'name' is selected as the user key. You can see that the elements are differentiated base on their 'name' attribute's value.
If no user key is defined - then the general approach is used instead.

Xompare configuration

The configuration file-name is 'Xompare.exe.config'.
The configuration of Xompare currently allows setting a user-key based on a pattern of a file-name, namely extension.

<XompareApplication defaultKey="">
  <KnownExtensions>
    <Extension pattern="*.xml" defaultKey="attr" />
    <Extension pattern="*.xaml" />
    <Extension pattern="*.xsl" />
    <Extension pattern="*.html" />
    <Extension pattern="*.htm" />
    <Extension pattern="*.config" defaultKey="name" />
    <Extension pattern="*.csproj" />
  </KnownExtensions>
  <GuiDefinitions>
    <XmlComparisonTab ignoreNameCase="false" ignoreValueCase="false" ignoreWhiteSpaces="false" />
  </GuiDefinitions>
</XompareApplication>
  1. The defaultKey of <XompareApplication> is used when there's no definition of a defaultKey attribute for the matched pattern of an XML file extension. When the calculated default-key is empty - the general method for a key is used.
  2. <GuiDefinitions> defines configuration for the GUI itself. In <XmlComparisonTab> can be found the configuration for the case-sensitive options.

Something about the source-library

The source library contains 2 important C# projects:
  1. The 'Utilities' project which Includes:
    1. A collection comparator which is used several times throughout the code for comparing collections and supplying 'only-original', 'only-target' and 'differences' according to defined keys.
    2. An XML parser to prepare for the collection comparator dictionaries of the original and target XML files. These dictionaries contains records of XML elements without children, keyed according to the explanation above.
  2. The 'Xompare' project which is actually the GUI utilizing the comparison tools given to it by the 'Utilities' project.

The 'Utilities' project can be used as well for other comparison tasks of collections of records keyed in some fashion.

Credits

Building this application, there are credits due to some that create libraries or resources being used freely by it, so, thank you:
  1. CLAP library for command-line parsing by Adrian Aisemberg
  2. Application logo, icon of Owl by Martin Berube
  3. DiffPlex library for finding differences between given texts

Last edited Jan 21, 2014 at 6:00 PM by adi3shilo, version 23