Menu

Using the right ElementQualifier for Comparison

Tanvi Kant
2015-08-21
2015-09-01
  • Tanvi Kant

    Tanvi Kant - 2015-08-21

    The two xmls I am trying to compare are:

    <root>
       <a id ="tanvi">test2</a>
       <a id ="aj">ram</a>
       <b id = "56">test</b>
       <d>
       <c foo = "bar">text</c>
       </d>
       <d>
       <c foo = "soo">textchange</c>
       </d>
     </root>
    

    and

    <root>
       <a id ="tanvi">test</a>
       <a id ="aj">ram</a>
       <b id = "56">test</b>
       <a id ="kartikey">test2</a>
       <d>
       <c foo = "bar">textchange</c>
       </d>
    </root>
    

    I want the application to give me the following differences:

    <a id ="tanvi">test2</a>    vs <a id ="tanvi">test</a>            text value change
    <a id ="kartikey">test2</a>   vs null                             not found
    <c foo = "bar">text</c>       vs <c foo = "bar">textchange</c>    text value change
    <d></d>                                   not found
    

    I have tried using RecursiveElementNameAndTextQualifier as well as the ElementNameAndAttributeQualifier. But I am not getting the desired results.

    My code is as follows:

    public class Main {
    
      public static void main(String[] args) {
    
          DetailedDiff detailedDiff = null;
          try {
              FileReader base = new FileReader(new File(
                      "C:\\xml\\Test2\\test_Swap.txt"));
              FileReader upgrade = new FileReader(new File(
                      "C:\\xml\\Test1\\test_Swap.txt"));
    
              XMLUnit.setIgnoreWhitespace(Boolean.TRUE);
              XMLUnit.setIgnoreAttributeOrder(Boolean.TRUE);
    
              try {
                  detailedDiff = new DetailedDiff(XMLUnit.compareXML(base,
                          upgrade));
                  // detailedDiff
                  // .overrideElementQualifier(new
                  // ElementNameAndAttributeQualifier());
                  detailedDiff
                          .overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
                  detailedDiff
                          .overrideDifferenceListener(new MyDifferenceListener());
              } catch (SAXException | IOException e) {
                  e.printStackTrace();
              }
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          }
    
          List<Difference> listOfDifferences = detailedDiff.getAllDifferences();
          for (Difference diff : listOfDifferences) {
    
              if (diff.getId() == 22) {
                  if ((diff.getControlNodeDetail().getValue().equals("null") && diff
                          .getTestNodeDetail().getValue().equals("#text"))
                          || (diff.getTestNodeDetail().getValue().equals("null") && diff
                                  .getControlNodeDetail().getValue()
                                  .equals("#text"))) {
                      System.out
                              .println("******************VALUE CHANGE*******************************");
                      System.out.print("Base Xpath: "
                              + diff.getControlNodeDetail().getXpathLocation()
                              + "\t");
                      System.out.println("Value: \'"
                              + diff.getControlNodeDetail().getValue() + "\'\t");
                      System.out.print("Test Node Xpath: "
                              + diff.getTestNodeDetail().getXpathLocation()
                              + "\t");
                      System.out.print("Value: "
                              + diff.getTestNodeDetail().getValue() + "\t");
    
                      System.out.println("Difference ID: " + diff.getId());
                      System.out.println("Difference: " + diff);
                      System.out.println("Description: " + diff.getDescription());
                      continue;
                  }
    
              }
    
              System.out
                      .println("*************************************************");
              System.out.print("Base Xpath: "
                      + diff.getControlNodeDetail().getXpathLocation() + "\t");
              System.out.println("Value: \'"
                      + diff.getControlNodeDetail().getValue() + "\'\t");
              System.out.print("Test Node Xpath: "
                      + diff.getTestNodeDetail().getXpathLocation() + "\'\t");
              System.out.print("Value: \'" + diff.getTestNodeDetail().getValue()
                      + "\'\t");
              System.out.println("Difference ID: " + diff.getId());
              System.out.println("Difference: " + diff);
              System.out.println("Description: " + diff.getDescription());
          }
    
      }
    }
    

    *I am using the DifferenceListener to ignore these differences:

       public class MyDifferenceListener implements DifferenceListener {
      private static final int[] IGNORE_VALUES = new int[] {
              DifferenceConstants.CHILD_NODELIST_LENGTH_ID,
              DifferenceConstants.CHILD_NODELIST_SEQUENCE_ID,
              DifferenceConstants.ATTR_SEQUENCE_ID,
              DifferenceConstants.HAS_CHILD_NODES_ID };
    
      static {
          Arrays.sort(IGNORE_VALUES);
      }
    
      private boolean isIgnoredDifference(final Difference difference) {
          int differenceId = difference.getId();
          for (int element : IGNORE_VALUES) {
              if (differenceId == element) {
                  return true;
              }
          }
          return false;
      }
    
      @Override
      public int differenceFound(final Difference difference) {
          if (isIgnoredDifference(difference)) {
              return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
          } else {
              return RETURN_ACCEPT_DIFFERENCE;
          }
      }
    
      @Override
      public void skippedComparison(final Node node, final Node node1) {
          // TODO Auto-generated method stub
    
      }
    }
    

    The ElementNameAndAttributeQualifier is giving me these results:

    *************************************************
    Base Xpath: /root[1]/a[1]/text()[1]   Value: 'test'   
    Test Node Xpath: /root[1]/a[1]/text()[1]' Value: 'test2'  Difference ID: 14
    Difference: Expected text value 'test' but was 'test2' - comparing <a ...>test</a> at /root[1]/a[1]/text()[1] to <a ...>test2</a> at /root[1]/a[1]/text()[1]
    Description: text value
    *************************************************
    Base Xpath: /root[1]/a[3] Value: 'a'  
    Test Node Xpath: /root[1]/d[1]'   Value: 'd'  Difference ID: 10
    Difference: Expected element tag name 'a' but was 'd' - comparing <a...> at /root[1]/a[3] to <d...> at /root[1]/d[1]
    Description: element tag name
    *************************************************
    Base Xpath: /root[1]/a[3] Value: '1'  
    Test Node Xpath: /root[1]/d[1]'   Value: '0'  Difference ID: 11
    Difference: Expected number of element attributes '1' but was '0' - comparing <a...> at /root[1]/a[3] to <d...> at /root[1]/d[1]
    Description: number of element attributes
    *************************************************
    Base Xpath: /root[1]/a[3]/@id Value: 'id' 
    Test Node Xpath: /root[1]/d[1]'   Value: 'null'   Difference ID: 2
    Difference: Expected attribute name 'id' but was 'null' - comparing <a...> at /root[1]/a[3]/@id to <d...> at /root[1]/d[1]
    Description: attribute name
    *************************************************
    Base Xpath: /root[1]/a[3]/text()[1]   Value: '3'  
    Test Node Xpath: /root[1]/d[1]/c[1]'  Value: '1'  Difference ID: 17
    Difference: Expected node type '3' but was '1' - comparing <a ...>test2</a> at /root[1]/a[3]/text()[1] to <c...> at /root[1]/d[1]/c[1]
    Description: node type
    ******************VALUE CHANGE*******************************
    Base Xpath: null  Value: 'null'   
    Test Node Xpath: /root[1]/d[1]/c[1]/text()[1] Value: #text    Difference ID: 22
    Difference: Expected presence of child node 'null' but was '#text' - comparing  at null to <c ...>text</c> at /root[1]/d[1]/c[1]/text()[1]
    Description: presence of child node
    *************************************************
    Base Xpath: /root[1]/d[1]/c[1]/@foo   Value: 'bar'    
    Test Node Xpath: /root[1]/d[2]/c[1]/@foo' Value: 'soo'    Difference ID: 3
    Difference: Expected attribute value 'bar' but was 'soo' - comparing <c foo="bar"...> at /root[1]/d[1]/c[1]/@foo to <c foo="soo"...> at /root[1]/d[2]/c[1]/@foo
    Description: attribute value
    

    The RecursiveElementNameAndTextQualifier is giving me these results:

    *************************************************
    Base Xpath: /root[1]/a[1] Value: 'a'  
    Test Node Xpath: /root[1]/d[1]'   Value: 'd'  Difference ID: 10
    Difference: Expected element tag name 'a' but was 'd' - comparing <a...> at /root[1]/a[1] to <d...> at /root[1]/d[1]
    Description: element tag name
    *************************************************
    Base Xpath: /root[1]/a[1] Value: '1'  
    Test Node Xpath: /root[1]/d[1]'   Value: '0'  Difference ID: 11
    Difference: Expected number of element attributes '1' but was '0' - comparing <a...> at /root[1]/a[1] to <d...> at /root[1]/d[1]
    Description: number of element attributes
    *************************************************
    Base Xpath: /root[1]/a[1]/@id Value: 'id' 
    Test Node Xpath: /root[1]/d[1]'   Value: 'null'   Difference ID: 2
    Difference: Expected attribute name 'id' but was 'null' - comparing <a...> at /root[1]/a[1]/@id to <d...> at /root[1]/d[1]
    Description: attribute name
    *************************************************
    Base Xpath: /root[1]/a[1]/text()[1]   Value: '3'  
    Test Node Xpath: /root[1]/d[1]/c[1]'  Value: '1'  Difference ID: 17
    Difference: Expected node type '3' but was '1' - comparing <a ...>test</a> at /root[1]/a[1]/text()[1] to <c...> at /root[1]/d[1]/c[1]
    Description: node type
    ******************VALUE CHANGE*******************************
    Base Xpath: null  Value: 'null'   
    Test Node Xpath: /root[1]/d[1]/c[1]/text()[1] Value: #text    Difference ID: 22
    Difference: Expected presence of child node 'null' but was '#text' - comparing  at null to <c ...>text</c> at /root[1]/d[1]/c[1]/text()[1]
    Description: presence of child node
    *************************************************
    Base Xpath: /root[1]/a[3]/@id Value: 'kartikey'   
    Test Node Xpath: /root[1]/a[1]/@id'   Value: 'tanvi'  Difference ID: 3
    Difference: Expected attribute value 'kartikey' but was 'tanvi' - comparing <a id="kartikey"...> at /root[1]/a[3]/@id to <a id="tanvi"...> at /root[1]/a[1]/@id
    Description: attribute value
    *************************************************
    Base Xpath: /root[1]/d[1]/c[1]/@foo   Value: 'bar'    
    Test Node Xpath: /root[1]/d[2]/c[1]/@foo' Value: 'soo'    Difference ID: 3
    Difference: Expected attribute value 'bar' but was 'soo' - comparing <c foo="bar"...> at /root[1]/d[1]/c[1]/@foo to <c foo="soo"...> at /root[1]/d[2]/c[1]/@foo
    Description: attribute value
    

    Which ElementQualifier should I use or override any method to get the desired results?

     
    • Paul Reisdorf

      Paul Reisdorf - 2015-09-01

      Try using this qualifier that compares XML nodes and attributes before comparing the text value. The RecursiveElementNameAndTextQualifier assumes nodes match if the node and text values match. In most cases you want to also only match if the node and and attributes also match before comparing the text of the node.

       

Log in to post a comment.