15

I am currently trying to use the XMLUnit library to compare two XML files. One of them, the candidate, is generated by my code from Java Objects (using JAXB) and the other one is the reference (I cannot modify it). Basically I am trying to prove that given a reference XML file I can unserialize it (using Jaxb and some classes of my own) then serialize it back to another file and still have the same content.

The library seems to furnish the services I need but when the generated file is not properly indented (in kind of a "pretty-print" version) the comparison fails and it doesn't when indentation is OK. For example when the candidate is generated there is no indentation, the content is a one-liner, if a indent it properly (manually) the comparison is OK.

Here is the error message generated by XMLUnit:

[different] Expected number of child nodes '3' but was '1'

Do you guys have any idea to solve this? Maybe the solution is to generate a pretty-print version of the candidate, in this case do you have an idea to combine it with the JAXB serialiser?

By the way if you now a better solution in Java to compare XML files I'll be glad to know it ;)

Thanks in advance for your help.

reef
  • 1,813
  • 2
  • 23
  • 36

2 Answers2

21

You can relax some of the constraints used by XMLUnit when comparing to trees by setting properties on the org.custommonkey.xmlunit.XMLUnit class.

In your case, you probably want:

XMLUnit.setIgnoreComments(true);
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);

You may also find the setIgnoredAttributeOrder property helpful as well.

Ophidian
  • 9,775
  • 2
  • 29
  • 27
0

Below is code to compare xml files

import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
public class XMLComparator {
public static void main(String[] args) {
    String xmlFile1 = "file1.xml";
    String xmlFile2 = "file2.xml";
    
    try {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();

        // Parse XML files into Document objects
        Document doc1 = builder.parse(new File(xmlFile1));
        Document doc2 = builder.parse(new File(xmlFile2));

        // Compare the documents
        boolean isEqual = compareXML(doc1.getDocumentElement(), doc2.getDocumentElement());
        
        if (isEqual) {
            System.out.println("The XML files are equivalent.");
        } else {
            System.out.println("The XML files are not equivalent.");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static boolean compareXML(Node node1, Node node2) {
    if (node1.getNodeType() != node2.getNodeType()) {
        return false;
    }

    if (node1.getNodeType() == Node.ELEMENT_NODE) {
        if (!node1.getNodeName().equals(node2.getNodeName())) {
            return false;
        }

        NamedNodeMap attrs1 = node1.getAttributes();
        NamedNodeMap attrs2 = node2.getAttributes();
        if (attrs1.getLength() != attrs2.getLength()) {
            return false;
        }

        for (int i = 0; i < attrs1.getLength(); i++) {
            Node attr1 = attrs1.item(i);
            Node attr2 = attrs2.getNamedItem(attr1.getNodeName());
            if (attr2 == null || !attr2.getNodeValue().equals(attr1.getNodeValue())) {
                return false;
            }
        }
    }

    NodeList children1 = node1.getChildNodes();
    NodeList children2 = node2.getChildNodes();
    if (children1.getLength() != children2.getLength()) {
        return false;
    }

    for (int i = 0; i < children1.getLength(); i++) {
        Node child1 = children1.item(i);
        boolean matched = false;
        for (int j = 0; j < children2.getLength(); j++) {
            Node child2 = children2.item(j);
            if (compareXML(child1, child2)) {
                matched = true;
                break;
            }
        }
        if (!matched) {
            return false;
        }
    }

    return true;
}
}
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 19 '23 at 12:20