比较XmlDocument是否相等(内容明智)

时间:2010-05-27 19:46:28

标签: c# xml xmldocument equality

如果我想比较XMlDocument的内容,是这样吗?

XmlDocument doc1 = GetDoc1();
XmlDocument doc2 = GetDoc2();

if(doc1 == doc2)
{

}

我没有检查它们是否是同一个对象引用,但是如果xml的CONTENTS是相同的。

5 个答案:

答案 0 :(得分:34)

尝试使用XLinq API上的DeepEquals方法。

XDocument doc1 = GetDoc1(); 
XDocument doc2 = GetDoc2(); 

if(XNode.DeepEquals(doc1, doc2)) 
{ 

} 

另见Equality Semantics of LINQ to XML Trees

答案 1 :(得分:11)

否。 XmlDocument不会覆盖Equals()方法的行为,因此,它实际上只是执行引用相等 - 在您的示例中将失败,除非文档实际上是相同的对象实例。

如果您想比较文档的内容(属性,元素,提交,PI等),您必须自己实现该逻辑。 请注意:这不是微不足道的。

根据您的具体情况,您可以从文档中删除所有非必要的空格(这本身可能很棘手),并比较生成的xml文本。这并不完美 - 它对于语义相同的文档而言是失败的,但在命名空间的使用和声明方式,或者某些值是否被转义,元素的顺序等方面都有所不同。正如我之前所说,XML比较并非易事。

您还需要明确定义两个XML文档“相同”的含义。元素或属性排序是否重要?案例(在文本节点中)是否重要?你应该忽略多余的CDATA部分吗?处理指令是否重要?完全限定和部分限定的命名空间怎么样?

在任何通用实现中,您可能希望将两个文档转换为某种规范形式(无论是XML还是其他表示形式),然后比较规范化的内容。

已经存在执行XML差异的工具,例如Microsoft XML Diff/Patch,您可以利用它来识别两个文档之间的差异。据我所知,该工具不是以源代码形式分发的...因此,要在嵌入式应用程序中使用它,您需要编写流程脚本(如果您打算使用它,则应首先验证许可条款是否允许其使用和重新分发)。

编辑: 如果您使用的是.NET 3.5 SP1,请查看@Max Toro's answer,因为显然XLinq中有一个可能有用的选项。很高兴知道它存在。

答案 2 :(得分:9)

一种简单的方法是比较OuterXml

var a = new XmlDocument();
var b = new XmlDocument();

a.LoadXml("<root  foo='bar'  />");
b.LoadXml("<root foo='bar'/>");

Debug.Assert(a.OuterXml == b.OuterXml);

答案 3 :(得分:0)

LBushkin是对的,这不是微不足道的。由于XML是字符串数据,因此您可以从技术上执行内容的哈希并比较它们,但这会受到像空格一样的影响。

您可以在两个文档之间执行结构化差异(也称为“XML diffgram”)并比较结果。例如,这就是.NET数据集跟踪变化的方式。

除此之外,您必须遍历DOM并将元素,属性和值相互比较。如果涉及到架构,那么您还必须考虑位置等等。

答案 4 :(得分:0)

通常,您想比较以不同顺序排列的XML字符串。使用此代码可以轻松完成

class Testing
{
    [Test]
    public void Test()
    {
        Assert.AreEqual(
            "<root><a></a><b></b></root>".SortXml()
            , "<root><b></b><a></a></root>".SortXml());
    }
}

public static class XmlCompareExtension
{
    public static string SortXml(this string @this)
    {
        var xdoc = XDocument.Parse(@this);

        SortXml(xdoc);

        return xdoc.ToString();
    }

    private static void SortXml(XContainer parent)
    {
        var elements = parent.Elements()
            .OrderBy(e => e.Name.LocalName)
            .ToArray();

        Array.ForEach(elements, e => e.Remove());

        foreach (var element in elements)
        {
            parent.Add(element);
            SortXml(element);
        }
    }
}