XNode.DeepEquals将selfclosing标记和结束标记视为不同

时间:2017-05-23 17:22:56

标签: c# .net xml

我想比较两个xml文档是否相等。我的一份文件有自动关闭标签,其他文件没有。

XNode node = XDocument.Parse("<Root/>");
XNode node2 = XDocument.Parse("<Root></Root>");

bool result = XNode.DeepEquals(node, node2);
Console.WriteLine(result);

Run it quickly

我认为"<Root/>"等同于"<Root></Root>",但DeepEquals表示它们不是(返回false)。

如何比较这两个文件是否相同?

ps:不受XNode约束。使用XmlDocument的解决方案也欢迎。

1 个答案:

答案 0 :(得分:2)

为了比较两个文件的相等性,应该在一定程度上对它们进行标准化。

Eric White撰写了几篇博文,详细介绍了高级规范化[1]和简单规范化[2]。

要修复空标记与自闭标记,后一篇文章更相关。

来自文章:

static XElement CloneElement(XElement element)
{
    return new XElement(element.Name,
        element.Attributes(),
        element.Nodes().Select(n =>
        {
            XElement e = n as XElement;
            if (e != null)
                return CloneElement(e);
            return n;
        })
    );
}

此代码将递归地将元素及其后代复制为规范化形式(使用默认的XElement构造)。这包括将空标签标准化为自闭标签。然后比较文档将按预期工作。

考虑以下XML:

<Foo>
    <Bar/>
    <Root/>
</Foo>

<Foo>
    <Bar></Bar>
    <Root></Root>
</Foo>

在每个元素上使用CloneElement后,它们将是相等的。

var node = XElement.Parse("<Foo><Bar/><Root/></Foo>");
var node2 = XElement.Parse("<Foo><Bar></Bar><Root></Root></Foo>");

XElement.DeepEquals(node, node2); // False
XElement.DeepEquals(CloneElement(node), CloneElement(node2)); // True

[1]:Equality Semantics of LINQ to XML Trees

[2]:Empty Elements and Self-Closing Tags