0 Replies Latest reply: Jan 31, 2013 4:17 AM by 928518 RSS

    XMLUnit: Element and Attribute ordering problem

    928518
      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.