Easy way to compare two XMLs for equality

The first thing to do is normalize to two XMLs, for this you can use a small method using Linq:

 

private static XElement Normalize(XElement element)

{

    if (element.HasElements)

    {

        return new XElement(

            element.Name,

            element.Attributes().Where(a => a.Name.Namespace == XNamespace.Xmlns)

            .OrderBy(a => a.Name.ToString()),

            element.Elements().OrderBy(a => a.Name.ToString())

            .Select(e => Normalize(e)));

    }

 

    if (element.IsEmpty)

    {

        return new XElement(element.Name, element.Attributes()

            .OrderBy(a => a.Name.ToString()));

    }

 

    return new XElement(element.Name, element.Attributes()

        .OrderBy(a => a.Name.ToString()), element.Value);

}

 

After both elements were normalized, simply you can compare both strings:

 

bool equal = Normalize(expected).ToString() ==

             Normalize(actual).ToString();

 

A nice place to use this is in unit tests, where you can do your own XML assert class:

 

public static class XmlAssert

{

    public static void AreEqual(

        XElement expected,

        XElement actual)

    {

        Assert.AreEqual(

            Normalize(expected).ToString(),

            Normalize(actual).ToString());

    }

 

    private static XElement Normalize(XElement element)

    {

        if (element.HasElements)

        {

            return new XElement(

                element.Name,

                element.Attributes()

                       .OrderBy(a => a.Name.ToString()),

                element.Elements()

                       .OrderBy(a => a.Name.ToString())

                       .Select(e => Normalize(e)));

        }

 

        if (element.IsEmpty)

        {

            return new XElement(

                element.Name,

                element.Attributes()

                       .OrderBy(a => a.Name.ToString()));

        }

 

        return new XElement(element.Name, element.Attributes()

            .OrderBy(a => a.Name.ToString()), element.Value);

    }

}

Published Friday, January 02, 2009 11:48 AM by marianor
Filed under:

Comments

No Comments