Search code examples
c#xmllinqexcept

use LINQ to XML to Programmatically get all differences between 2 xml files


I am using c sharp 5.0 and using LINQ to XML I try to programmatically get the differences between 2 xml files my first files is as simple as :

<?xml version="1.0" encoding="UTF-8" ?> 
<table name="MYTABLE">
<columns>
<column name="MY_ID" type="NUMBER"/> 
<column name="M_NAME" type="VARCHAR2" /> 
<column name="MY_PARENT_ID" type="VARCHAR2" /> 
<column name="MY_CAPTION" type="VARCHAR2" />
</columns>
</table>

and my second xml file is as simple as :

<?xml version="1.0" encoding="UTF-8" ?> 
<table name=" MYTABLE ">
<columns>
<column name="MY_ID" type="NUMBER"/> 
<column name="M_NAME" type="VARCHAR2" /> 
<column name="MY_PARENT_ID" type="NUMBER" />
</columns>
</table>

and my code is as simple as :

XDocument doc1 = XDocument.Load(@"Path\table1.xml");
XDocument doc2 = XDocument.Load(@"Path\table2.xml");
var cols1 = doc1.Descendants("column") ;
var cols2 = doc2.Descendants("column") ;
var itemsOnFirstFileOnly = cols1.Except(cols2);
var itemsOnSecondFileOnly = cols2.Except(cols1);

but to my surprise itemsOnFirstFileOnly returned ALL of columns that exist on table1.xml (not only MY_PARENT_ID & MY_CAPTION ) and itemsOnSecondFileOnly returned ALL of the columns that exist in table2.xml (not only MY_PARENT_ID),so why not Except doesn’t work as expected ??


Solution

  • You have to implement Equals on your Column-class so that Except knows when two Columns are equal:

    class Column 
    {
        bool Equals(object other) 
        {
            // ...
            // skip further checks for simplicity
            // ...
    
            Column o = (Column) other;
            return o.Name == this.Name && o.Type == this.Type  ;
        }
    }
    

    If you do not implement this method Except will just check for reference-equality which can never be true because your columns come from differenct contexts (files in your case).

    EDIT: As you are comparing XNodes the thing is much easier because you can use the XNodeEqualityComparer-class which has its own Equals-implementation that exactly fit your needs as seen here. Thus the following should work:

    var itemsOnFirstFileOnly = cols1.Except(cols2, new XNodeEqualityComparer());