Click here to Skip to main content
15,891,473 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
How to get the child nodes missing on comparing 2 Xml files using XmlDiff?

I want to show only the missing element nodes in the input Xml comparing with the standard Xml. With XmlDiff node value changes also are shown. I just want the missing node elements and not the node value mismatch.
Posted
Comments
John C Rayan 7-Oct-15 7:32am    
Did you explore XmlDiff.Options
Maciej Los 7-Oct-15 9:25am    
Sample xml data, please!
What you mean by saying: "missing nodes"?

1 solution

I have no idea what you mean by "show only the missing element nodes in the input Xml comparing with the standard Xml", especially what standard xml is... Nevertheless...

There are - at least - two solutions:
1) XML validation using schema (XSD file)
How to: Validate Using XSD (LINQ to XML)[^]
XML Schema (XSD) Validation with XmlSchemaSet[^]
XmlDocument.Validate Method (ValidationEventHandler)[^]

2) Data comparison using custom class (and class collection) and IEqualityComparer<T>[^] and Enumerable.Except()[^] method:
Second method is bit harder to explain, so... the best method is to show an example (please read comments).
Imagine, you have a list of Books with the following properties: Id, Title, Author. Example class may look like:
C#
public class Book
{
    private int id = 0;
    private string author = string.Empty;
    private string title = string.Empty;

    public Book(int _id, string _author, string _title)
    {
        id = _id;
        author = _author;
        title = _title;
    }

    public int Id
    {
        get { return id; }
        set { id = value; }
    }

    public string Author
    {
        get { return author; }
        set { author = value; }
    }

    public string Title
    {
        get { return title; }
        set { title = value; }
    }
}


IEqualityComparer class may look like:
C#
public class BookComparer : IEqualityComparer<Book>
{

    public bool Equals(Book a, Book b)
    {
        if (Object.ReferenceEquals(a, b)) return true;

        //Check whether the products' properties are equal.
        return a != null && b != null && a.Title.Equals(b.Title) && a.Author.Equals(b.Author);
    }

    public int GetHashCode(Book obj)
    {
        int hashBookTitle = obj.Title == null ? 0 : obj.Title.GetHashCode();
        int hashBookAuthor = obj.Author == null ? 0 : obj.Author.GetHashCode();

        //Calculate the hash code for the book
        return hashBookTitle ^ hashBookAuthor;
    }
}

As you can see, Id property is ignored. Only Title and Author of book are compared.

Now, sample xml data, which we'll use in next step:
XML
<books>
  <book id="1">
    <author>James Booldog</author>
    <title>The honor </title>
  </book>
  <book id="2">
    <author>Joanne Clipboard</author>
    <title>Paranoya</title>
  </book>
  <book id="3">
    <author>Jamie Douplo</author>
    <title>Lego star</title>
  </book>
</books>


Usage:
C#
void Main()
{
    //define xml content
    //first xml
    string x1 = @"<?xml version='1.0' encoding='utf-8'?>
    <books>
        <book id='1'>
            <author>James Booldog</author>
            <title>The honor </title>
        </book>
        <book id='2'>
            <author>Joanne Clipboard</author>
            <title>Paranoya</title>
        </book>
        <book id='3'>
            <author>Jamie Douplo</author>
            <title>Lego star</title>
        </book>
    </books>";
    //second xml
    string x2 = @"<?xml version='1.0' encoding='utf-8'?>
    <books>
        <book id='1'>
            <author>James Booldog</author>
            <title>The honor </title>
        </book>
        <book id='2'>
            <author>Joanne Clipboard</author>
            <title>Paranoya</title>
        </book>
        <book id='3'>
        </book>
    </books>";
    //create xml documents
    XDocument doc1 = XDocument.Parse(x1);
    //doc1.Dump();
    XDocument doc2 = XDocument.Parse(x2);
    //returns List<Book>
    List<Book> bks1 = doc1.Descendants("book")
        .Select(x=>new Book
            (
                (int)x.Attribute("id"),
                (string)x.Element("author"),
                (string)x.Element("title")
            )).ToList<Book>();
    //returns IEnumerable<Book>
    var bks2 = doc2.Descendants("book")
        .Select(x=>new Book
            (
                (int)x.Attribute("id"),
                (string)x.Element("author"),
                (string)x.Element("title")
            ));

    //compare List(of Book) using BookComparer class, which inherits from IEqualityComparer
    var missingBooks1 = bks1.Except(bks2, new BookComparer());
}


In case when you use custom collection class:
C#
public class Books : CollectionBase
{

    public void Add(Book b)
    {
        //b.Id = List.Count;
        List.Add(b);
    }

    public void AddRange(List<Book> books)
    {
        foreach(Book b in books)
        {
            List.Add(b);
        }
    }

    public void AddRange(IEnumerable<Book> books)
    {
        foreach(var b in books)
        {
            List.Add((Book)b);
        }
    }

    public void Remove(int index)
    {
        if(index<0 || index>List.Count-1)
        {
            throw new IndexOutOfRangeException("Invalid index!");
        }
        else
        {
            List.Remove(index);
        }
    }

}


a comparison might be achieved this way:
C#
//using Books class which inherits from CollectionBase
Books books1 = new Books();
books1.AddRange(bks1);
Books books2 = new Books();
books2.AddRange(bks2);
//compare
var missingBooks2 = books1.Cast<Book>().Select(a=>a).Except(books2.Cast<Book>().Select(b=>b), new BookComparer());



Final note: This is very basic example. I hope you get an idea.
Try to implement your own method to compare xml data!
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900