Monday, May 15, 2023

How to compare two XML files in Java - XMLUnit Example

The XMLUnit library can be used to compare two XML files in Java. Similar to JUnit, XMLUnit can also be used to test XML files for comparison by extending the XMLTestcase class. It is a rich library and provides a detailed comparison of XML files. Btw, comparing XML is completely different than comparing String in Java or comparing objects using equals(), as two XML which contains different comments and whitespace can be equals, which is not true for String or character comparison. Also while comparing XML files, it's very important to know exactly which content or part is different and XMLUnit not only shows the content which is different but also the XPath of elements which is getting compared.

The heart and soul of XMLUnit are the DifferenceEngine class but we won't use it directly. Instead, you will use Diff and DetailedDiff the two important classes for XML comparison. They provide a comparison engine for comparing XML. 

The XMLUnit library not only compares complete XML documents but also can perform a lot of useful activities related to XPath e.g. it can check if an XPATH exists or not exists. It can even check if XPath contains the expected value or not.

The XMLUnit library can also provide validation support. So, if you want to check if an XML file confirms to DTD or not, you can do that using XMLUnit's Validator class. The default validation is using DTD but if you want to confirm against XSD schema, you can do that by using option Validator.useXMLSChema flag.




Java program to compare two XML documents in Java.

It internally uses JAXP for XSLT transformation and XPath evaluation. It at least needs JAXP 1.2 which is included in Java 1.5 but if you want to use a more advanced XPath engine based upon JAXP 1.3 then you need to include Java 1.5 or higher version in the classpath. 

In this Java and XML tutorial, you will learn how to compare two XML documents in Java by following a simple example using XMLUnit.Overall it's a nice, handy utility library for testing and comparing XML files in Java applications.

Here is a complete Java program to compare two XML documents using XMLUnit library. In this example, we have two XML files source.xml and target.xml, later is created by copying the former file and I have made one change, in a phone number to compare these two XML files. In order to compare and show differences between XML documents, I have created two static methods compareXML() and printDifferences().

The code to read XML file is very similar to the code of reading text files in Java, we are reading XML files as InputStream and passing it to compareXML() as Reader object. Real XML comparison begins in this method with Diff and DetailedDiff class.

The DetailedDiff returns all differences as List, if there is no different than the size of this List would be zero and we can say two XML files are identical in data. printDifference() method takes this List of Differences and prints it on Console. If you look difference provided by XMLUnit, you will find that it shows both what is the difference and where is that difference occur by showing complete XPATH.




Java Program to compare XML files using XMLUnit

package test;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.xml.sax.SAXException;

/**
  *
  * Java program to compare two XML files using XMLUnit example

  * @author Javin Paul
  */
public class XMLComparator {
 
 
    public static void main(String args[]) throws FileNotFoundException, 
                                                  SAXException, IOException {
     
        // reading two xml file to compare in Java program
        FileInputStream fis1 = new FileInputStream("C:/test/source.xml");
        FileInputStream fis2 = new FileInputStream("C:/test/target.xml");
     
        // using BufferedReader for improved performance
        BufferedReader  source 
                        = new BufferedReader(new InputStreamReader(fis1));
        BufferedReader  target 
                        = new BufferedReader(new InputStreamReader(fis2));
     
        //configuring XMLUnit to ignore white spaces
        XMLUnit.setIgnoreWhitespace(true);
     
        //comparing two XML using XMLUnit in Java
        List differences = compareXML(source, target);
     
        //showing differences found in two xml files
        printDifferences(differences);
   
    }    
 
    public static List compareXML(Reader source, Reader target) throws
                  SAXException, IOException{
     
        //creating Diff instance to compare two XML files
        Diff xmlDiff = new Diff(source, target);
     
        //for getting detailed differences between two xml files
        DetailedDiff detailXmlDiff = new DetailedDiff(xmlDiff);
     
        return detailXmlDiff.getAllDifferences();
    }
 
    public static void printDifferences(List differences){
        int totalDifferences = differences.size();
        System.out.println("===============================");
        System.out.println("Total differences : " + totalDifferences);
        System.out.println("================================");
     
        for(Difference difference : differences){
            System.out.println(difference);
        }
    }
}

You can see that we are first printing the total number of differences between two XML files and then printing each difference by going through the List which contains each Difference.

How to compare two XML files in Java using XMLUnit


Input XML files :

source.xml

<employees>
  <employee id="1">
    <name>James</name>
    <department>Sales</department>
    <phone>8034832190</phone>
    </employee>
 </employees>
   


target.xml

<employees>
  <employee id="1">
    <name>James</name>
    <department>Sales</department>
    <phone>9843267462</phone>
    </employee>
 </employees>


Output:
===============================
Total differences : 1
================================
Expected text value '8034832190' but was '9843267462' - 
comparing 8034832190 at /employees[1]/employee[1]/phone[1]/text()[1] 
to 9843267462 at /employees[1]/employee[1]/phone[1]/text()[1]

Alternatively, you can also compare XML files as a text file using a comparison tool like Beyond Compare or WinMerge, as mentioned in my previous post about 10 Essential tools for Java Programmers.

How to test XML files using XMLUnit



XMLUnit Example 2:

Now let's remove all newline characters from target.xml and convert it as one line XML file for comparison. Now our target.xml will look like

<employees>  <employee id="1">    <name>James</name>     
<department>Sales</department>    <phone>9843267462</phone>    
</employee> </employees>

Output:
===============================
Total differences : 13
================================
Expected number of child nodes '3' but was '1' - 
comparing at /employees[1] to at /employees[1]

All these differences while comparing source and target XML files comes because of white space and they are not true differences.

Since in a real-world scenario, it's always possible to compare two XML files with a difference in whitespace, it's best to ignore white space while comparing XML files and thankfully XMLUnit can be configured to ignore whitespace by using static method XMLUnit.setIgnoreWhitespace(true).

Now if you re-run this Java program after adding a call to XMLUnit.setIgnoreWhitespace(true), with the same input, you will once again see a single difference as shown below.

===============================
Total differences : 1
================================
Expected text value '8034832190' but was '9843267462

Similarly you can also ignore comments by calling XMLUnit.setIgnoreComments(true) before comparing XML files in Java.  You can even use overloaded method XMLUnit.compareXML(source, target) to compare two XML files. This method takes Document, Reader, or String to get XML content.


That's all on how to compare two XML files in Java using XMLUnit example. XMLUnit library is rich and powerful and provides several other options to compare XML documents including differences in XPath, comparing transformations etc.

XMLUnit library can also be used as JUnit by extending XMLTestCase class, which provides methods like assertXMLEqual(org.w3c.dom.Document source, org.w3c.dom.Document target) and several other overloaded versions for testing XML files. You can check if an XPath exists or not and whether it contains the expected value or not. It's a very good tool to write automated tests if your program is generating or modifying XML files.


Other Java XML tutorials you may like
  • What is the difference between DOM and SAX parser in Java? (answer)
  • How to format dates while converting XML to Java using JAXB? (example)
  • Step by Step guide to parsing XML using SAX parser in Java? (tutorial)
  • How to read XML files using DOM Parser in Java? (tutorial)
  • How to escape XML Special character in Java String? (tutorial)
  • How to parse XML documents using JDOM Parser in Java? (tutorial)
  • How to create and evaluate XPath Expressions in Java? (guide)
  • Top 10 XSLT Transformation Interview Questions? (FAQ)
  • Top 10 XML Interview Questions for Java Programmers? (FAQ)

Thanks for reading this tutorial so far, if you really like this tutorial then please like our Facebook page and don't forget to share it with your friends and colleagues. If you have any suggestions or feedback then please drop a comment. If you just want to do one thing at the moment, then read Test Driven to learn more practical and automated ways to test your applications. 

19 comments:

  1. Hi, As shown in the output can i Remove the extra data that is present like i just want the differences and not the sentences that are after AT, basically i want to ignore the nodes, is there any way out for the same

    Expected text value '8034832190' but was '9843267462' - comparing 8034832190
    at /employees[1]/employee[1]/phone[1]/text()[1] to 9843267462 at /employees[1]/employee[1]/phone[1]/text()[1]

    ReplyDelete
    Replies
    1. Hi, can you tell me how to remove that extra data in output which you have pasted here

      Delete
  2. Hi, thank for the post, Great explanation.
    I am trying to implement it.
    However I am getting error in printDifferences(List differences) method on for loop
    for(Difference difference : differences){
    System.out.println(difference);
    }
    Type mismatch: cannot convert from element type Object to Difference

    Any solution for it?

    ReplyDelete
  3. @Priya Pawar : use the List as generic to fix the element type Object issue.
    wherever the List is defined conver the List of type Difference.
    "List"

    thanks.

    ReplyDelete
  4. Hi,
    Is there any method, to print what all the nodes & attributes compared(or) same in target and source files.

    ReplyDelete
  5. Hello @Unknown, I am not sure, need to check, You can also take a look at the API or code of XMLUnit.

    ReplyDelete
  6. Hi ,Instead of differences I want to check which nodes and tags are having same values.Do we have inbuilt method for that also?

    ReplyDelete
  7. Got to check mate, did you check the API? they sure have something.

    ReplyDelete
  8. can i get the line number where the exact difference is been noticed between the two files

    ReplyDelete
  9. Hello @Unknown, you may be, check the API if they have any such methods, I haven't check them in a while but it should be easy when you add that in your classpath and let Eclipse or IntelliJ telling you all the methods.

    ReplyDelete
  10. I want to compare Oly the attributes is it possible

    ReplyDelete
    Replies
    1. Yes it is possible, you can provide your own implementation of DifferenceEvaluator, please see if this link helps. https://link.medium.com/c9E9ojQERjb

      Delete
  11. i have this line underlined with red
    for(Difference difference : differences)

    ReplyDelete
  12. Hi I'm trying to use this but I'm getting NoClassDefFoundError: org/custommonkey/xmlunit/Diff, I've checked in repository it has the particular class but still it is not working

    ReplyDelete
  13. maybe your JAR doesn't have that class, check which version of XMLUNit has that class and use that JAR file.

    ReplyDelete
  14. i have added my jar but getting differences in red in eclipse

    ReplyDelete
  15. the dependency itself is not resolving for me. Took the dependency from mvn repository site. but when it is trying to resolve, it throws error. Can someone help on this? This is what I have:

    org.custommonkey.xmlunit
    com.springsource.org.custommonkey.xmlunit
    1.2.0

    getting this error:

    "Cannot resolve org.custommonkey.xmlunit:com.springsource.org.custommonkey.xmlunit:1.2.0"

    ReplyDelete
  16. how to find order mismatches.

    ReplyDelete
  17. Guys , I am working on a utility using xmlunit 2 https://link.medium.com/c9E9ojQERjb

    ReplyDelete