0

Hi I am trying to compare content of two xml files using xmlunit
Here are my input xmls

reference.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book>
        <name>abc</name>
        <isbn>9971-5-0210-0</isbn>
        <author>abc</author>
        <category></category>
    </book>
    <book>
        <name>def</name>
        <isbn>9971-5-0222-0</isbn>
        <author>def</author>
    </book>
</books>

compare.xml

<?xml version="1.0" encoding="UTF-8"?>
    <books>
        <book>
            <name>abc</name>
            <isbn>9971-5-0210-0</isbn>
            <author>abc</author>
            <category></category>
        </book>
        <book>
            <name>def</name>
            <isbn>9971-5-0222-0</isbn>
            <author>def</author>
        </book>
        <book>
            <name>ghi</name>
            <isbn>9971-5-0222-0</isbn>
            <author>test authora</author>
        </book>
    </books>

Here we can observe in the compare.xml there are 3 book nodes.

and I am printing the total differences and count as below

 DetailedDiff detDiff = new DetailedDiff(diff);
    List differences = detDiff.getAllDifferences();
    System.out.println("Total differences:-->"+differences.size());
    for (Object object : differences) {
        Difference difference = (Difference)object;
        System.out.println("***********************");
        System.out.println(difference);
        System.out.println("***********************");
    }

output:

**Total differences:-->4

Expected number of child nodes '5' but was '7' - comparing at /books[1] to at /books[1]



Expected text value ' ' but was ' ' - comparing at /books[1]/text()[3] to at /books[1]/text()[3]



Expected presence of child node 'null' but was 'book' - comparing at null to at /books[1]/book[3]



Expected presence of child node 'null' but was '#text' - comparing at null to at /books[1]/text()[4]


Instead is there any way so that i can consider change as only 1 (because I consider only one book node is added ignoring inner tags inside ) and also customize the output to our customized message

Shabarinath Volam
  • 789
  • 5
  • 19
  • 48

2 Answers2

2

The first step is to ignore element content whitespace which is going to remove the second and forth difference.

XMLUnit.setIgnoreWhitespace(true);

In order to suppress one of the other two differences you need to override the DifferenceListener and explicitly ignore one of them. From what you describe you'd prefer to only see the CHILD_NODE_NOT_FOUND differences.

    detDiff.overrideDifferenceListener(new DifferenceListener() {
            @Override
            public int differenceFound(Difference difference) {
                return difference.getId() == DifferenceConstants.CHILD_NODELIST_LENGTH_ID
                    ? RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL
                    : RETURN_ACCEPT_DIFFERENCE;
            }
            @Override
            public void skippedComparison(Node control, Node test) { }
        });
Stefan Bodewig
  • 3,260
  • 15
  • 22
0

One solution may be to parse the xml files into java objects and comparing them later.

In this example I am not using xmlunit, it is based on xstream, I hope it will help you :

Book class

    public class Book {

        private String  name;
        private String  isbn;
        private String  author;
        private String  category;

        public String getName() {
            return name;
        }

        public void setName(final String name) {
            this.name = name;
        }

        public String getIsbn() {
            return isbn;
        }

        public void setIsbn(final String isbn) {
            this.isbn = isbn;
        }

        public String getAuthor() {
            return author;
        }

        public void setAuthor(final String author) {
            this.author = author;
        }

        public String getCategory() {
            return category;
        }

        public void setCategory(final String category) {
            this.category = category;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + (author == null ? 0 : author.hashCode());
            result = prime * result + (category == null ? 0 : category.hashCode());
            result = prime * result + (isbn == null ? 0 : isbn.hashCode());
            result = prime * result + (name == null ? 0 : name.hashCode());
            return result;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Book other = (Book) obj;
            if (author == null) {
                if (other.author != null) {
                    return false;
                }
            } else if (!author.equals(other.author)) {
                return false;
            }
            if (category == null) {
                if (other.category != null) {
                    return false;
                }
            } else if (!category.equals(other.category)) {
                return false;
            }
            if (isbn == null) {
                if (other.isbn != null) {
                    return false;
                }
            } else if (!isbn.equals(other.isbn)) {
                return false;
            }
            if (name == null) {
                if (other.name != null) {
                    return false;
                }
            } else if (!name.equals(other.name)) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "Book [name=" + name + ", isbn=" + isbn + ", author=" + author + ", category=" + category + "]";
        }

    }

Boks class (with main method):

    public class Books {

        private final List<Book>    books;

        public Books() {
            books = new ArrayList<Book>();
        }

        public void add(final Book b) {
            books.add(b);
        }

        public List<Book> getBooks() {
            return books;
        }

        @Override
        public String toString() {
            return books.toString();
        }

        public static void main(final String[] args) {
            final XStream xstream = new XStream();
            xstream.alias("books", Books.class);
            xstream.alias("book", Book.class);
            xstream.addImplicitCollection(Books.class, "books");
            final Books ref = (Books) xstream.fromXML(Book.class.getClassLoader().getResourceAsStream("reference.xml"));
            final Books compare = (Books) xstream.fromXML(Book.class.getClassLoader().getResourceAsStream("compare.xml"));
            System.out.println(ref);
            System.out.println(compare);
            final List<Book> rbooks = new ArrayList<Book>(ref.getBooks());
            final List<Book> cbooks = new ArrayList<Book>(compare.getBooks());
            rbooks.removeAll(cbooks);
            System.out.println("Missing books in compare : " + rbooks);
            rbooks.clear();
            rbooks.addAll(ref.getBooks());
            cbooks.removeAll(rbooks);
            System.out.println("Extra books in compare : " + cbooks);
        }

    }
rafalopez79
  • 2,046
  • 4
  • 27
  • 23