Comparing XML - xmlunit/user-guide GitHub Wiki

Representing Comparison and Differences

XMLUnit's diff system breaks down the whole process of comparing two pieces of XML into atomic parts. Each such part is represented as a Comparison. A Comparison encapsulates a type of comparison like "the name of an XML element", "the number of child nodes" or "the value of an attribute" and the two pieces that are to be compared - those two pieces are called Details in this context and know about the DOM nodes that get compared as well as the XPath location of said nodes inside their respective documents and the value WRT to the comparisons at hand. For "the name of an XML element" or "the number of child nodes" the DOM nodes would be element nodes and the values would be the QName/XmlQualifiedName of the element or a number respectively.

A Comparison only knows what is getting compared, it doesn't judge whether the values are equal or different. This is for the DifferenceEngine or rather the DifferenceEvaluator to decide.

A Difference combines a Comparison with the DifferenceEvaluator's decision. In most situations where Difference objects are part of XMLUnit's API it is assumed the comparison has not led to an EQUAL result, hence the name.

A Diff is the overall result of comparing two pieces of XML, it is a wrapper around a potentially empty collection of Differences.

Obtaining Differences

There are several ways to obtain the differences between two pieces of XML. The lowest level of abstraction is provided by the (I)DifferenceEngine described below. On top of it a fluent DiffBuilder hides away the complexity of setting up the difference engine instance. CompareMatcher and CompareConstraint provide Hamcrest matchers/NUnit Constraints on top of DiffBuilder.

Formatting Results

To format a Comparison object to a human readable string you can use the DefaultComparisonFormatter.

See ComparisonFormatter for more options.

(DOM)DifferenceEngine

The DifferenceEngine is part of the low level API that offers access to all features provided by the library.

Finding differences between two XML documents depends on the context much more than one would expect. XMLUnit provides extension APIs that allows you to fine-tune the whole comparison process.

The first decision one has to take is which parts of the documents need to get compared with each other and which can be ignored completely? This area is surprisingly complex and needs several different hooks to accommodate all needs. Selecting Nodes describes the corresponding interfaces in more depth.

Secondly, what constitutes a difference that's really interesting? Are differences in XML namespace prefixes relevant or not? Is element order significant? It's the DifferenceEvaluator's job to determine that.

Finally, should all differences get found or do we only need to know whether the documents are different at all? This is for ComparisonController to decide.

ComparisonController

The default ComparisonController lets DifferenceEngine evaluate all differences between test and control XML. If the evaluation should stop after the first found difference you must use the ComparisonControllers.StopWhenDifferent instead.

See also DiffBuilder.withComparisonController()

Monitoring the Comparison Process

As comparisons are performed ComparisonListener event listeners will get notified of any kind of comparison (ComparisonListener), only those comparisons that resulted in an EQUAL outcome (MatchListener) or only those comparisons that resulted in real differences (DifferenceListener). There are three different add*Listener methods in Java and three different events to subscribe to in .NET.

Subscribing a ComparisonListener is the only way to obtain the result of a comparison when using the low level API of DifferenceEngine directly.