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 Detail
s 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 Difference
s.
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.
DifferenceEngine
(DOM)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.