您如何比较两个XML文档?

Nei*_*ski 60 .net c# xml xmldocument compare

作为一些广泛的单元测试的基类的一部分,我正在编写一个辅助函数,它在C#(.NET)中递归地将一个XmlDocument对象的节点与另一个XmlDocument对象的节点进行比较.一些要求:

  • 第一个文档是源代码,例如我希望XML文档看起来像什么.因此,第二个是我想要找到差异的那个,它不能包含不在第一个文档中的额外节点.
  • 当发现太多显着差异时必须抛出异常,并且应该通过人们对该描述进行瞥见来容易理解.
  • 子元素顺序很重要,属性可以按任何顺序排列.
  • 有些属性是可以忽略的; 特别是xsi:schemaLocationxmlns:xsi,虽然我希望能够通过在哪些.
  • 名称空间的前缀必须在属性和元素中都匹配.
  • 元素之间的空白是无关紧要的.
  • 元素将要么有子元素 InnerText,但不能同时.

虽然我正在废弃一些东西:有没有人写过这样的代码,是否有可能在这里分享?

顺便说一下,你会把第一个和第二个文件称为什么?我一直把它们称为"源"和"目标",但它感觉不对,因为是我希望目标看起来像,否则我抛出异常.

Dan*_*mal 54

Microsoft有一个可以使用的XML diff API

  • 这很酷!不幸的是,它没有做的一件事是让我忽略某些属性。 (2认同)
  • 请注意,XML 记事本 (https://github.com/microsoft/XmlNotepad) 内置了“XMLDiff”,它直观地显示 XMLDiff diffgram 中编码的差异。只需打开 XML,然后转到“查看”->“比较 XML 文件”。您甚至可以控制选项中的“XmlDiffOptions”。 (2认同)

小智 6

这段代码不能满足您的所有要求,但它很简单,我正在用于我的单元测试。属性顺序无关紧要,但元素顺序很重要。不比较元素内部文本。我在比较属性时也忽略了大小写,但您可以轻松删除它。

public bool XMLCompare(XElement primary, XElement secondary)
{
    if (primary.HasAttributes) {
        if (primary.Attributes().Count() != secondary.Attributes().Count())
            return false;
        foreach (XAttribute attr in primary.Attributes()) {
            if (secondary.Attribute(attr.Name.LocalName) == null)
                return false;
            if (attr.Value.ToLower() != secondary.Attribute(attr.Name.LocalName).Value.ToLower())
                return false;
        }
    }
    if (primary.HasElements) {
        if (primary.Elements().Count() != secondary.Elements().Count())
            return false;
        for (var i = 0; i <= primary.Elements().Count() - 1; i++) {
            if (XMLCompare(primary.Elements().Skip(i).Take(1).Single(), secondary.Elements().Skip(i).Take(1).Single()) == false)
                return false;
        }
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

  • 我无法将我的属性设置为 Count() (2认同)

Mir*_*rek 6

为了比较自动化测试中的两个 XML 输出,我发现了XNode.DeepEquals.

比较两个节点的值,包括所有后代节点的值。

用法:

var xDoc1 = XDocument.Parse(xmlString1);
var xDoc2 = XDocument.Parse(xmlString2);

bool isSame = XNode.DeepEquals(xDoc1.Document, xDoc2.Document);
//Assert.IsTrue(isSame);
Run Code Online (Sandbox Code Playgroud)

参考:https://learn.microsoft.com/en-us/dotnet/api/system.xml.linq.xnode.deepequals ?view=netcore-2.2

  • 请注意,此比较在属性顺序上存在错误:https://github.com/dotnet/dotnet-api-docs/issues/830 (2认同)

run*_*rig 5

比较XML文档很复杂.谷歌为xmldiff(甚至是微软的解决方案)提供一些工具.我已经通过几种方式解决了这个问题.我使用XSLT对元素和属性进行排序(因为有时它们会以不同的顺序出现,我不关心它),并过滤掉我不想比较的属性,然后使用XML :: DiffXML :: SemanticDiff perl模块,或者在每个文档上打印相当于每个元素和属性的单独行,并在结果上使用Unix命令行diff.


San*_*uri 5

尝试XMLUnit.该库可用于Java和.Net


cwi*_*lls 5

https://github.com/CameronWills/FatAntelope Microsoft XML Diff API 的另一个替代库。它具有 XML 比较算法,可以对两个 XML 文档进行无序比较并产生最佳匹配。

它是此处描述的 X-Diff 算法的 C# 端口: http://pages.cs.wisc.edu/~yuanwang/xdiff.html

免责声明:我写的:)