This question already has answers here:
Compare two XML strings ignoring element order
(9 answers)
Closed 6 years ago.
I am comparing a saved example xml with a live marshalled xml in my JUnit testing. Validating the presence of a key value pair in the xml.
I am making use of XmlUnit 2.1.0 specifically
My xml is as follows:
<entries>
<entry>
<key>delete</key>
<value>ENABLED</value>
</entry>
<entry>
<key>view</key>
<value>DISABLED</value>
</entry>
<entry>
<key>create</key>
<value>DISABLED</value>
</entry>
</entries>
The order of the entries can vary. I'm unsure how to get it to validate correctly since it sees a different key value as a difference in the xml even though it's just an order change.
I am asserting similarity with the follow assertion in JUnit:
assertThat(marshalledXml, isSimilarTo(Input.fromFile("path/to/example.xml").ignoreWhitespace().ignoreComments());
I suspect I may need to make use of XPath matchers or the DefaultNodeMatchers with an ElementSelector.
Yes, you need to provide an ElementSelector that "knows" which nodes to pick for comparison in your specific case.
For most of the document the name of the element seems to be what you should use. At least that's true for entries, key and value. For entry elements you want to compare those elements, that have matching nested text in the key element that is their immediate child, right?
I think this translates to
ElementSelectors.conditionalBuilder()
.whenElementIsNamed("entry")
.thenUse(ElementSelectors.byXPath("./key", ElementSelectors.byNameAndText))
.elseUse(ElementSelectors.byName)
.build();
See https://github.com/xmlunit/user-guide/wiki/SelectingNodes for a more detailed discussion of the ElementSelector options. Your XML is pretty close to the table example used in the introduction and discussed in the next sections.
Related
Let's say I have the following XML document:
<Offices>
<Office name="P">
<Counter>1000</Counter>
</Office>
<Office name="K">
<Counter>1006</Counter>
</Office>
</Offices>
With that document I need to perform the following in Java:
Parse the XML.
Get the value of Counter given a certain value for a name attribute.
Update the XML with a new value for Counter for exactly this Office.
For 2. I have considered using XPath but editing/updating the XML seems to be not that easy this way.
How could I go through the XML finding a certain office name and update its counter? The XML itself won't be large, only something like 20 office entries max.
You can try looking at this answer:
https://stackoverflow.com/a/5059411/1571550
It seems pretty straightforward and generic solution.
The XSD schema I am working with, calls for either an international or domestic address:
"/mns:PhysicalAddress/mns:DomesticAddress/mns:City"
or
"/mns:PhysicalAddress/mns:InternationalAddress/mns:City"
It is being used as a parameter in a Java method as in XMLUtils.BuildField(Document doc, String xpath).
I know I can go straight to the Java object that created that doc and use the auto-generated beans to query elements, but I prefer remaining within the concise realm of XPath. Is this possible?
If so, how do I write an XPath expression selects mns:City regardless of whether it is international or domestic address?
Note: This in Java, not Javascript, HTML or XSLT, so I don't think <xsl:if> is relevant here.
You could go with finding all Cities that have either parent:
//mns:City[(parent::mns:DomesticAddress|parent::mns:InternationalAddress)]
If you need to also ensure that the address is in the physical address:
//mns:City[(parent::mns:DomesticAddress|parent::mns:InternationalAddress)[parent::mns:PhysicalAddress]]
Alternatively, instead of reversing the hierarchy, you do a * and check the name:
/mns:PhysicalAddress/*[name()="mns:DomesticAddress" or name()="mns:InternationalAddress"]/mns:City
Depending in the precise structure of your XML,
/mns:PhysicalAddress/*/mns:City
may be enough, if that pulls in too much then the clearest option is probably just to use the two alternatives you already have, separated by a |:
/mns:PhysicalAddress/mns:DomesticAddress/mns:City | /mns:PhysicalAddress/mns:InternationalAddress/mns:City
Or slightly more concise but (in my opinion) less clear:
/mns:PhysicalAddress/*[self::mns:DomesticAddress | self::mns:InternationalAddress]/mns:City
Comparing these two snippets of XML:
testXml:
<ELEMENT1>
<CHILD1></CHILD1>
</ELEMENT1>
actualXml:
<ELEMENT1>
<CHILD1>notEmpty</CHILD1>
</ELEMENT1>
using:
Diff diff = new Diff(testXml, actualXml);
Detailed detailedDiff = new DetailedDiff(diff);
Now detailedDiff.getAllDifferences(); will return a DifferenceConstants.HAS_CHILD_NODES_ID difference and if you print the difference to the console it looks like this:
Expected presence of child nodes to be 'false' but was 'true' - comparing <CHILD1...> at /ELEMENT1[1]/CHILD1[1] to <CHILD1...> at /ELEMENT1[1]/CHILD1[1]
My question is, why is the difference of type DifferenceConstants.HAS_CHILD_NODES_ID and not DifferenceConstants.TEXT_VALUE_ID? The structure of the two XML-snippets are the same, but the text value of the two differs.
So, why doesn't that trigger a difference?
Try to use this ElementQualifier:
Diff diff = new Diff(testXml, actualXml);
diff.overrideElementQualifier(new RecursiveElementNameAndTextQualifier() );
Detailed detailedDiff = new DetailedDiff(diff);
here is the description from javadoc:
public RecursiveElementNameAndTextQualifier()
Uses element names and the text nested an arbitrary level of child
elements deeper into the element to compare elements. Checks all
nodes, not just first child element.
Does not ignore empty text nodes.
The interested thing here is the "does not ignore empty text nodes".
It seems that the default ElementQualifier treats empty nodes as a missing node, and only checks for the first error related to one node. So in your case, possibly solely the "HAS_CHILD_NODES_ID" is thrown instead of including also "TEXT_VALUE_ID".
At least, RecursiveElementNameAndTextQualifier goes deeper.
I have a very specific requirment of comparing 2 xml strings in java. I have 2 xml strings. Original and modified. I need to compare the original xml string with the modified and find out what has been modified.
For example:
Original xml is
<Mycontacts>
<contact>
<firstName>Robert</firstName>
<PhoneNumber>9053428756</PhoneNumber>
<lastName>Bobbling</lastName>
<mobile>4168014523</mobile>
</contact>
<contact>
<firstName>Lily</firstName>
<PhoneNumber>9053428756</PhoneNumber>
<lastName>Bobbling</lastName>
<mobile>4168014523</mobile>
</contact>
</Mycontacts>
Modified xml:
<Mycontacts>
<contact>
<firstName>Robert</firstName>
<PhoneNumber>40454321333</PhoneNumber>
<lastName>Bobbling</lastName>
<mobile>4168014523</mobile>
</contact>
</Mycontacts>
As 1 contact is modified here and 1 id deleted I want to form 2 xml's trees. 1 is modify_xml and 1 is delete xml
modify xml:
<contact>
<firstName>Robert</firstName>
<PhoneNumber>40454321333</PhoneNumber>
<lastName>Bobbling</lastName>
<mobile>4168014523</mobile>
</contact>
delete xml:
<contact>
<name>Lily</name>
</contact>
How can this be done using java API's? Is parsing each node and creating a map for each contact entry a good option?
http://xmlunit.sourceforge.net/
I would parse the XML files to Java objects and compare those, assuming that the XML layout is not changing over time. You can use XStream or JAXB to do that.
Very difficult problem in the general case, for example if you want to detect that the element names have changed but the values have stayed the same, or if you want to detect that two elements are both still present but the order has been reversed. It's a lot easier if you know something about the structure of your data, and for example you are able to distinguish which values act as identifiers, so the problem reduces to finding an element in the other file with the same identifier and then asking which of its non-identifying properties have changed.
The essential point is that you need to say a lot more about the requirements before one can attempt a design.
I'm building an XSD to generate JAXB objects in Java. Then I ran into this:
<TotalBugs>
<Bug1>...</Bug1>
<Bug2>...</Bug2>
...
<BugN>...</BugN>
</TotalBugs>
How do I build a sequence of elements where the index of the sequence is in the element name? Specifically, how do I get the 1 in Bug1
You don't want to do it in this way, XML has a top-down order by nature. Consequently, you don't have to enumerate yourself:
<totalBugs>
<bug><!-- Here comes 1st bug --></bug>
<bug><!-- Here comes 2nd bug --></bug>
...
<bug><!-- Here comes last bug --></bug>
</totalBugs>
You can access the 1st bug node in the list by the XPath expression:
/totalBugs/bug[1]
Note, indexes start by W3C standard at 1. Please refer to for further readings to w3schools.
I'm pretty sure XSD won't support what you need. However you can use <xsd:any> for that bit of the schema, then use something lower-level than JAXB to generate the XML for that particular part. (I think your generated classes will have fields like protected List<Element> any; which you can fill in using DOM).