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);

    }

}

3 Comments

  • This is for the comparison of values.
    What if we do need to compare the structure of two xmls.

  • It compares structure well, but not schema sequence or node order.

  • That its not the same, XNodeEqualityComparer fails just with the order of the attributes:

    var expected = new XElement("Sample", new XAttribute("a1", "a1"), new XAttribute("a2", "a2"));
    var actual = new XElement("Sample", new XAttribute("a2", "a2"), new XAttribute("a1", "a1"));
    Console.WriteLine(new XNodeEqualityComparer().Equals(expected, actual));

    But I can use XNodeEqualityComparer or DeepEquals after the ordering of the Attributes and Nodes.

Comments have been disabled for this content.