I have an XML message like so:
<root>
<elementA>something</elementA>
<elementB>something else</elementB>
<elementC>yet another thing</elementC>
</root>
I want to compare a message of this type produced by a method under test to an expected message, but I don't care about elementA
. So, I'd like the above message to be considered equal to:
<root>
<elementA>something different</elementA>
<elementB>something else</elementB>
<elementC>yet another thing</elementC>
</root>
I'm using the latest version of XMLUnit.
I'm imagining that the answer involves creating a custom DifferenceListener
; I just don't want to reinvent the wheel if there's something ready to use out there.
Suggestions that use a library other than XMLUnit are welcome.
Things have changed a lot for XMLUnit since this question was answered.
You can now easily ignore a node when using a DiffBuilder
:
final Diff documentDiff = DiffBuilder
.compare(expectedSource)
.withTest(actualSource)
.withNodeFilter(node -> !node.getNodeName().equals(someName))
.build();
If you then call documentDiff.hasDifferences()
nodes added to filter will be ignored.
I wound up implementing a DifferenceListener
that takes a list of node names (with namespaces) to ignore textual differences for:
public class IgnoreNamedElementsDifferenceListener implements DifferenceListener {
private Set<String> blackList = new HashSet<String>();
public IgnoreNamedElementsDifferenceListener(String ... elementNames) {
for (String name : elementNames) {
blackList.add(name);
}
}
public int differenceFound(Difference difference) {
if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
if (blackList.contains(difference.getControlNodeDetail().getNode().getParentNode().getNodeName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
public void skippedComparison(Node node, Node node1) {
}
}
I would use XSLT and the identity transform to filter out elements I want to ignore, and compare the results.
See XSL: how to copy a tree, but removing some nodes ? earlier on SO.
You can now try ${xmlunit.ignore}
in XMLUnit 2.6.0 (add dependency xmlunit-placeholders). Sample code is as below.
Diff diff = DiffBuilder
.compare(expectedXML)
.withTest(actualXML)
.withDifferenceEvaluator(new PlaceholderDifferenceEvaluator())
.build();
Expected XML:
<root>
<elementA>${xmlunit.ignore}</elementA>
<elementB>something else</elementB>
<elementC>yet another thing</elementC>
</root>
Actual XML:
<root>
<elementA>anything</elementA>
<elementB>something else</elementB>
<elementC>yet another thing</elementC>
</root>
Do notice that currently the ${xmlunit.ignore} only supports text node and attribute value ignorance, as can be seen from the unit tests.
public class IgnoreNamedElementsDifferenceListener implements DifferenceListener {
private Set<String> blackList = new HashSet<String>();
public IgnoreNamedElementsDifferenceListener(String ... elementNames) {
for (String name : elementNames) {
blackList.add(name);
}
}
public int differenceFound(Difference difference) {
if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
if (blackList.contains(difference.getControlNodeDetail().getNode().getParentNode().getNodeName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
public void skippedComparison(Node node, Node node1) {
}
}
How to invoke this own implementation to my method to see the differences after the specific node ignored for the comparison.?
来源:https://stackoverflow.com/questions/1241593/how-do-i-ignore-certain-elements-when-comparing-xml