I am using xmlunit 2.5.0.
Below are my two xml string : One is the controlxml
and one is testxml
.
String controlXml = "<flowers><flower><f1 name = \"Roses\"/></flower><flower><f1 name = \"Daisy\"/></flower><flower><f1 name = \"Crocus\"/></flower></flowers>";
String testXml = "<flowers><flower><f1 name = \"Daisy\"/></flower><flower><f1 name = \"Roses\"/></flower><flower><f1 name = \"Crocus\"/></flower></flowers>";
Here i am comparing these two string xmls using xmlunit.
My java code is:
org.xmlunit.diff.Diff myDiff = DiffBuilder.compare(controlXml).withTest(testXml)
.checkForSimilar()
.withNodeMatcher(new
DefaultNodeMatcher(ElementSelectors.conditionalBuilder()
.whenElementIsNamed("f1")
.thenUse(ElementSelectors.byName)
.elseUse(ElementSelectors.byNameAndText)
.build()))
.build();
Getting error:
***********************
Expected attribute value 'Roses' but was 'Daisy' - comparing <f1 name="Roses"...> at /flowers[1]/flower[1]/f1[1]/@name to <f1 name="Daisy"...> at /flowers[1]/flower[1]/f1[1]/@name (DIFFERENT)
***********************
***********************
Expected attribute value 'Daisy' but was 'Roses' - comparing <f1 name="Daisy"...> at /flowers[1]/flower[2]/f1[1]/@name to <f1 name="Roses"...> at /flowers[1]/flower[2]/f1[1]/@name (DIFFERENT)
***********************
I want to get no error since Rose is present in the testxml. Why is Rose in controlxml is being compared to Daisy in testxml even though i have rose in the testxml and i have ElementSelectors.byName
and whenElementIsNamed("f1")
.
Which ElementSelector should I use?
Your
.whenElementIsNamed("f1")
.thenUse(ElementSelectors.byName)
means your "f1" elements will be in compared in document order. They all have the same name after all. You obviously feel the value of the name
attribute is what identifies the "f1"s to compare. If the "f1" would be siblings then a simple
.thenUse(ElementSelectors.byNameAndAttributes("name"))
should work. byNameAndAttributes
takes a varargs list of attributes whose values must match in addition to the element name.
Unfortunately they are not siblings and you must tell XMLUnit which "flower" elements to pick when traversing the tree. When XMLUnit picks up the wrong "flower"s, it is never going to see the "f1" you consider the same.
The full solution for your example is
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.conditionalBuilder()
.whenElementIsNamed("flower")
.thenUse(ElementSelectors.byXPath("./f1", ElementSelectors.byNameAndAttributes("name")))
.elseUse(ElementSelectors.byNameAndText)
.build()))