This discussion is archived
0 Replies Latest reply: Jan 31, 2013 2:17 AM by 928518 RSS

XMLUnit: Element and Attribute ordering problem

928518 Newbie
Currently Being Moderated
I have a question regarding “Similar” and “Identical”. In the following example given on XMLUnit help page:
<author>Dan Brown</author>
<category></category>
And
<category></category>
<author>Dan Brown</author>
The output comes out to be:

Similar? true
Identical? false
***********************
Expected sequence of child nodes ’5′ but was ’7′ – comparing at /books[1]/book[1]/author[1] to at /books[1]/book[1]/author[1]
***********************
***********************
Expected sequence of child nodes ’7′ but was ’5′ – comparing at /books[1]/book[1]/category[1] to at /books[1]/book[1]/category[1]
***********************


My question how can we “NOT” include in the output such non-identical information? My problem is that I have a long xml documents to compare. There are cases, where the differences are related to orderring and in addition to others.

But when I get the total output, it gets kind of difficult to find the actual differences (non-orderring) related.

I have to manually skip the non-important information (orderring differences) from the actual differences for example if anything is missing in the reference documents or have different content etc.

Have said that, I read somewhere that such "orderring" problems can be solved with my own "custom DifferenceListener".

So I did the following, (the whole class):
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URL;
import java.util.List;

import org.w3c.dom.Node;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.custommonkey.xmlunit.DifferenceConstants;
import org.custommonkey.xmlunit.DifferenceListener;
import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier;
import org.custommonkey.xmlunit.ElementNameAndTextQualifier;
import org.custommonkey.xmlunit.ElementNameQualifier;
import org.custommonkey.xmlunit.MatchTracker;
import org.custommonkey.xmlunit.NodeDetail;
import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.examples.MultiLevelElementNameAndTextQualifier;
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
import org.xml.sax.SAXException;

public class XMLComparator {

     public static void main(String[] args) {
          URL url1 = XMLComparator.class.getResource("reference.xml");
          URL url2 = XMLComparator.class.getResource("comparison.xml");
          FileReader fr1 = null;
          FileReader fr2 = null;
          try {
               fr1 = new FileReader(url1.getPath());
               fr2 = new FileReader(url2.getPath());
          } catch (FileNotFoundException e) {
               e.printStackTrace();
          }

          XMLUnit.setIgnoreComments(Boolean.TRUE);
          XMLUnit.setIgnoreWhitespace(Boolean.TRUE);
          XMLUnit.setNormalizeWhitespace(Boolean.TRUE);
          XMLUnit.setIgnoreDiffBetweenTextAndCDATA(Boolean.TRUE);
          XMLUnit.setIgnoreAttributeOrder(Boolean.TRUE);
          
          XMLUnit.setCompareUnmatched(Boolean.FALSE); 
          
          
          try {
               Diff diff = new Diff(fr1, fr2);
                              
               diff.overrideDifferenceListener(new DifferenceListener() {
                    
                    @Override
                    public void skippedComparison(Node arg0, Node arg1) {
                         // TODO Auto-generated method stub
                    }
                    
                    @Override
                     public int differenceFound(Difference diff) { 
                       if (diff.getId() == DifferenceConstants.CHILD_NODELIST_SEQUENCE_ID) 
                    {
                       return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;  
                       }
                         
                       return RETURN_ACCEPT_DIFFERENCE;
                   }
                    
                    
                    
               });
                              
               System.out.println(" Similar ? " + diff.similar());
               System.out.println(" Identical ? " + diff.identical());
               
               

               DetailedDiff detDiff = new DetailedDiff(diff);

               detDiff.overrideMatchTracker(new MatchTrackerImpl());
               detDiff.overrideElementQualifier(new ElementNameAndTextQualifier());
               
               

               List differences = detDiff.getAllDifferences();
               

               for (Object object : differences) {
                    Difference difference = (Difference) object;
                    System.out.println("***********************");
                    System.out.println(difference);

                    System.out.println("***********************");
               }

          } catch (SAXException e) {
               e.printStackTrace();
          } catch (IOException e) {
               e.printStackTrace();
          }
     }

}

class MatchTrackerImpl implements MatchTracker {

     public void matchFound(Difference difference) {
          if (difference != null) {
               NodeDetail controlNode = difference.getControlNodeDetail();
               NodeDetail testNode = difference.getTestNodeDetail();

               String controlNodeValue = printNode(controlNode.getNode());
               String testNodeValue = printNode(testNode.getNode());

               if (controlNodeValue != null) {
                    // System.out.println("####################");
                    // System.out.println("Control Node: " + controlNodeValue);
               }
               if (testNodeValue != null) {
                    // System.out.println("Test Node: " + testNodeValue);
                    // System.out.println("####################");
               }
          }
     }

     private static String printNode(Node node) {
          if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
               StringWriter sw = new StringWriter();
               try {
                    Transformer t = TransformerFactory.newInstance()
                              .newTransformer();
                    t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
                    t.transform(new DOMSource(node), new StreamResult(sw));
               } catch (TransformerException te) {
                    System.out.println("nodeToString Transformer Exception");
               }
               return sw.toString();

          }
          return null;
     }
}
reference.xml
<?xml version="1.0" encoding="UTF-8"?>
<UsernameToken>
     <OtherSrvcName>EXCURSION_AND_TICKETS</OtherSrvcName>
     <OtherSrvcName>TRAVELGUIDE</OtherSrvcName>
</UsernameToken>
comparison.xml
<?xml version="1.0" encoding="UTF-8"?>
<UsernameToken>
     <OtherSrvcName>TRAVELGUIDE</OtherSrvcName>
     <OtherSrvcName>EXCURSION_AND_TICKETS</OtherSrvcName>
</UsernameToken>
The output:

Similar ? false
Identical ? false


This to some degree resolved my original problem, but my question is why Similar is false? Shouldn't it be 'true' ?

Secondly, on my slightly changing the XMLs, the entire output then yielded the same original response, which i am not interested in.

reference.xml
<?xml version="1.0" encoding="UTF-8"?>
<UsernameToken>
     <OtherSrvcPref>
          <OtherSrvcName>EXCURSION_AND_TICKETS</OtherSrvcName>
     </OtherSrvcPref>
     <OtherSrvcPref>
          <OtherSrvcName>TRAVELGUIDE</OtherSrvcName>
     </OtherSrvcPref>
</UsernameToken>
comparision.xml
<?xml version="1.0" encoding="UTF-8"?>
<UsernameToken>
     <OtherSrvcPref>
          <OtherSrvcName>TRAVELGUIDE</OtherSrvcName>
     </OtherSrvcPref>
     <OtherSrvcPref>
          <OtherSrvcName>EXCURSION_AND_TICKETS</OtherSrvcName>
     </OtherSrvcPref>
</UsernameToken>
Output:

Similar ? false
Identical ? false
***********************
Expected presence of child node 'OtherSrvcName' but was 'null' - comparing <OtherSrvcName...> at /UsernameToken[1]/OtherSrvcPref[1]/OtherSrvcName[1] to at null
***********************
***********************
Expected presence of child node 'null' but was 'OtherSrvcName' - comparing at null to <OtherSrvcName...> at /UsernameToken[1]/OtherSrvcPref[1]/OtherSrvcName[1]
***********************
***********************
Expected presence of child node 'OtherSrvcName' but was 'null' - comparing <OtherSrvcName...> at /UsernameToken[1]/OtherSrvcPref[2]/OtherSrvcName[1] to at null
***********************
***********************
Expected presence of child node 'null' but was 'OtherSrvcName' - comparing at null to <OtherSrvcName...> at /UsernameToken[1]/OtherSrvcPref[2]/OtherSrvcName[1]
***********************


Now why am i getting the 'Expected presence...' messages in the output? Shouldn't it just produce the same output as in the previous case, i.e.

Similar ? false
Identical ? false



I don't understand this difference in the behaviour of the output? Could someone please help me out here..

Thanks.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points