Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 比较XML文件是否相等的最佳方法是什么?_C#_.net_Xml_Unit Testing_Comparison - Fatal编程技术网

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

C# 比较XML文件是否相等的最佳方法是什么?,c#,.net,xml,unit-testing,comparison,C#,.net,Xml,Unit Testing,Comparison,我正在使用.NET 2.0,最近的一次代码更改使我以前的Assert.AreEqual调用(比较了两个XML字符串)无效。在新的代码库中,XML中只有一个元素实际上是不同的,所以我希望通过对所有其他元素的比较,可以得到我想要的结果。比较需要以编程方式完成,因为它是单元测试的一部分 起初,我考虑使用几个XmlDocument实例。但后来我发现: 看起来它可能会工作,但我对堆栈溢出反馈感兴趣,以防有更好的方法 如果可能的话,我希望避免为此添加另一个依赖项 类似问题 这实际上取决于您要检查的“

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

起初,我考虑使用几个XmlDocument实例。但后来我发现:

看起来它可能会工作,但我对堆栈溢出反馈感兴趣,以防有更好的方法

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

类似问题

这实际上取决于您要检查的“差异”


现在,我们正在使用MicrosoftXMLDiff:

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

例如:

xml
的角度来看是相等的

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

您可能会发现将XML解析为XML文档并基于XPath查询进行断言调用的脆弱性更小。下面是一些我经常使用的助手断言方法。每个节点都有一个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文件的内容可以具有不同的格式,并且在测试相等性时仍然被认为是相同的(从DOM的角度来看),因此需要确定相等性的度量值,例如,是否忽略了格式?元数据被忽略了吗?等等,定位很重要,有很多边缘情况

通常,您会创建一个类来定义相等规则并将其用于比较,如果您的比较类实现了
IEqualityComparer和/或IEqualityComparer
接口,那么您的类也可以在一组内置框架列表中用作相等测试实现。另外,当然,你可以有你需要的数量,根据你的要求,以不同的方式衡量平等性

i、 e

IEnumerable.Contains
IEnumerable.Equals
词典等的结构

我最终通过以下代码得到了我想要的结果:

private static void ValidateResult(string validationXml, XPathNodeIterator iterator, params string[] excludedElements)
    {
        while (iterator.MoveNext())
        {
            if (!((IList<string>)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);
            }
        }
    }
接下来,我创建一个XPathExpression实例,如下所示:

XPathExpression expression = XPathExpression.Compile("/blah/*");
我在使用以下表达式创建迭代器后调用该方法:

XPathNodeIterator iterator = nav.Select(expression);

我仍然在想如何进一步优化它,但现在它已经成功了。

我编写了一个带有序列化断言的小库

样本:

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

我提出了一种创建简单XML路径的方法

static XElement MakeFromXPath(string xpath)
{
    XElement root = null;
    XElement parent = null;
    var splits = xpath.Split('/'); //split xpath into parts
    foreach (var split in splits)
    {
        var el = new XElement(split);
        if (parent != null)
            parent.Add(el);
        else
            root = el; //first element created, set as root
        parent = el;
    }
    return root;
}
示例用法:

var-element=MakeFromXPath(“My/Path/To/element”)”

元素
将包含以下值:

<My>
  <Path>
    <To>
      <Element></Element>
    </To>
  </Path>
</My>


我通过问题中链接到的博客帖子找到了这个链接。如果可能的话,我希望避免添加另一个依赖项。然后我想你必须决定什么是“区别”,并用XmlDocuments、XpathNavigators等开发自己的算法。。。但我认为您正在寻找“业务差异”,而不是“xml差异”。在本例中,我知道两个文档之间的结构将是相同的(没有缺少或额外的元素)。只是元素的值是否相同。谢谢Jeremy,这看起来是一个很好的解决方案。我会尝试一下。因为这个问题是第一次提出的,所以提出了一个重复的问题,得到了一个更好的答案::Use Linq:
XNode.DeepEquals(doc1,doc2)
static XElement MakeFromXPath(string xpath)
{
    XElement root = null;
    XElement parent = null;
    var splits = xpath.Split('/'); //split xpath into parts
    foreach (var split in splits)
    {
        var el = new XElement(split);
        if (parent != null)
            parent.Add(el);
        else
            root = el; //first element created, set as root
        parent = el;
    }
    return root;
}
<My>
  <Path>
    <To>
      <Element></Element>
    </To>
  </Path>
</My>