Sunday, April 16, 2017

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 object using equals(), as two XML which contains different comment 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 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 comparison engine for comparing XML. The XMLUnit library not only compares complete XML document 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 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 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 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 return all differences as List, if there is no difference 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
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 total number of differences between two XML files and then printing each different 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 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 contain the expected value or not. It's a very good tool to write automated tests if your program is generating or modifying XML files.

Further Reading
Advanced Unit Testing
XML Fundamentals
RESTFul Services in Java using Jersey
Core Java, Volume II--Advanced Features

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 file using DOM Parser in Java? (tutorial)
  • How to escape XML Special character in Java String? (tutorial)
  • How to parse XML document 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 with your friends and colleagues. If you have any suggestion 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. 

No comments :

Post a Comment