比较XML文件是否相同的最佳方法是什么?

我正在使用.NET 2.0,最近的代码更改使我之前的Assert.AreEqual调用失效(它比较了两个XML字符串)。 在新的代码库中,只有一个XML元素实际上是不同的,所以我希望对所有其他元素进行比较会得到我想要的结果。 比较需要以编程方式完成,因为它是unit testing的一部分。

起初,我正在考虑使用几个XmlDocument实例。 但后来我发现了这个: http : //drowningintechnicaldebt.com/blogs/scottroycraft/archive/2007/05/06/comparing-xml-files.aspx

看起来它可能会起作用,但我对Stack Overflow反馈很感兴趣,以防有更好的方法。

如果可能的话,我想避免为此添加另一个依赖项。

类似的问题

  • NUnit是否有XML断言?
  • 你会如何比较两个XML文档?

这实际上取决于你想要检查的“差异”。

现在,我们正在使用Microsoft XmlDiff: http : //msdn.microsoft.com/en-us/library/aa302294.aspx

您可能会发现将XML解析为XmlDocument并将您的Assert调用基于XPath Query不太脆弱。 以下是我经常使用的一些辅助断言方法。 每个都使用XPathNavigator,您可以通过在XmlDocument上或从文档中检索的任何节点上调用CreateNavigator()来获取它。 使用的一个例子是:

  XmlDocument doc = new XmlDocument( "Testdoc.xml" ); XPathNavigator nav = doc.CreateNavigator(); AssertNodeValue( nav, "/root/foo", "foo_val" ); AssertNodeCount( nav, "/root/bar", 6 ) private static void AssertNodeValue(XPathNavigator nav, string xpath, string expected_val) { XPathNavigator node = nav.SelectSingleNode(xpath, nav); Assert.IsNotNull(node, "Node '{0}' not found", xpath); Assert.AreEqual( expected_val, node.Value ); } private static void AssertNodeExists(XPathNavigator nav, string xpath) { XPathNavigator node = nav.SelectSingleNode(xpath, nav); Assert.IsNotNull(node, "Node '{0}' not found", xpath); } private static void AssertNodeDoesNotExist(XPathNavigator nav, string xpath) { XPathNavigator node = nav.SelectSingleNode(xpath, nav); Assert.IsNull(node, "Node '{0}' found when it should not exist", xpath); } private static void AssertNodeCount(XPathNavigator nav, string xpath, int count) { XPathNodeIterator nodes = nav.Select( xpath, nav ); Assert.That( nodes.Count, Is.EqualTo( count ) ); } 

xml字符串上进行简单的字符串比较并不总是有效。 为什么?

例如:

xml角度来看是相等的..

有转换算法使xml看起来总是相同,它们被称为规范化算法。 .Net支持规范化。

我写了一个带有断言的小型库,用于序列化, 源码 。

样品:

 [Test] public void Foo() { ... XmlAssert.Equal(expected, actual, XmlAssertOptions.IgnoreDeclaration | XmlAssertOptions.IgnoreNamespaces); } 

的NuGet

由于XML文件的内容可以具有不同的格式,并且在测试相等性时仍然被认为是相同的(从DOM的角度来看),您需要确定该等式的度量是什么,例如是否忽略格式化? 元数据被忽略等等是重要的,很多边缘情况。

通常,您将创建一个定义相等规则的类并将其用于比较,如果您的比较类实现了IEqualityComparer and/or IEqualityComparer接口,那么您的类可以在一堆内置框架列表中用作同样测试实现也是如此。 此外,您当然可以根据需要以不同的方式衡量相等性。

 IEnumerable.Contains IEnumerable.Equals The constructior of a Dictionary etc etc 

我最终得到了我想要的结果,使用以下代码:

 private static void ValidateResult(string validationXml, XPathNodeIterator iterator, params string[] excludedElements) { while (iterator.MoveNext()) { if (!((IList)excludedElements).Contains(iterator.Current.Name)) { Assert.IsTrue(validationXml.Contains(iterator.Current.Value), "{0} is not the right value for {1}.", iterator.Current.Value, iterator.Current.Name); } } } 

在调用方法之前,我以这种方式在XmlDocument实例上创建一个导航器:

 XPathNavigator nav = xdoc.CreateNavigator(); 

接下来,我创建一个XPathExpression实例,如下所示:

 XPathExpression expression = XPathExpression.Compile("/blah/*"); 

在使用表达式创建迭代器后调用该方法:

 XPathNodeIterator iterator = nav.Select(expression); 

我还在想办法如何进一步优化它,但它现在可以解决问题。