C# 中的 Xpath:从 xml "list"(兄弟姐妹)中获取元素

Xpath in C# : getting element out of a xml "list" (siblings)

我的问题很简单。我正在使用 XPath 从 xml 文件中检索信息。我的目标是比较 2 XML 个文件,它们应该是相同的。我对 "single" 节点没有问题。当有兄弟姐妹时,我的问题就来了。

看起来像这样:

XPathDocument expectedDocument = new XPathDocument("C:\expected.xml");
XPathDocument testedDocument = new XPathDocument("C:\tested.xml");
XPathNavigator expectedNav = expectedDocument.CreateNavigator();
XPathNavigator testedNav = testedDocument.CreateNavigator();
XPathNodeIterator expectedIterator;
XPathNodeIterator testedIterator;
string expectedStr;
string testedStr;
string parameter;
parameter = "/DonneesDepot/Identification/@CoclicoFacturation";
expectedStr = expectedNav.SelectSingleNode(parameter).Value;
testedStr = testedNav.SelectSingleNode(parameter).Value;
CompareValues(expectedStr, testedStr, parameter);

效果很好。现在变得复杂的是这种 XML :

  <Surtaxe>
        <Zone CodeZoneSurtaxe="1" NbPlisZone="0" PoidsZone="0" />
        <Zone CodeZoneSurtaxe="2" NbPlisZone="2" PoidsZone="2" />
  </Surtaxe>

我希望能够确保 "Surtaxe" 的内容在两个文件中是相同的(记住顺序并不重要),所以我尝试了这个:

parameter = "/DonneesDepot/Facturation/Surtaxe/Zone/@PoidsZone";
expectedIterator = expectedNav.Select(parameter);
testedIterator = testedNav.Select(parameter);
while (expectedIterator.MoveNext() && testedIterator.MoveNext())
{
    CompareValues(expectedIterator.Current.Value, testedIterator.Current.Value, parameter);
}

但即使 XML 都包含这两行,它们有时顺序也不相同,所以我的 while 循环不起作用。

比较下面两个最简单的是什么(这个比较的预期结果是"Equality")

<Surtaxe>
    <Zone CodeZoneSurtaxe="1" NbPlisZone="1" PoidsZone="1" />
    <Zone CodeZoneSurtaxe="2" NbPlisZone="0" PoidsZone="0" />
</Surtaxe>

<Surtaxe>
    <Zone CodeZoneSurtaxe="2" NbPlisZone="0" PoidsZone="0" />
    <Zone CodeZoneSurtaxe="1" NbPlisZone="1" PoidsZone="1" />
</Surtaxe>

谢谢

这会做你想做的,你可能需要为你的真实对象改变它,但这应该让你开始。我证明了2个解决方案。一个朴素的 n^2 解决方案和一个应该更快的排序方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XmlCompare
{
    using System.IO;
    using System.Xml.Linq;
    using System.Xml.XPath;

    class Program
    {

        private static string xml1 = "<Surtaxe>" + "<Zone CodeZoneSurtaxe=\"2\" NbPlisZone=\"0\" PoidsZone=\"0\" />"
                                     + "<Zone CodeZoneSurtaxe=\"1\" NbPlisZone=\"1\" PoidsZone=\"1\" />" + "</Surtaxe>";

        private static string xml2 = "<Surtaxe>" + "<Zone CodeZoneSurtaxe=\"1\" NbPlisZone=\"1\" PoidsZone=\"1\" />"
                                     + "<Zone CodeZoneSurtaxe=\"2\" NbPlisZone=\"0\" PoidsZone=\"0\" />" + "</Surtaxe>";

        private static void Main(string[] args)
        {

            var expectedDoc = XDocument.Load(new StringReader(xml1));
            var testedDoc = XDocument.Load(new StringReader(xml2));
            var success = true;

            //naive
            foreach (var node in expectedDoc.Descendants("Surtaxe").First().Descendants())
            {
                if (testedDoc.Descendants(node.Name).FirstOrDefault(x => x.ToString()== node.ToString()) == null)
                {
                    success = false;
                    break;
                }
            }

            //sort
            var sortedExpected = xml1.ToList();
            sortedExpected.Sort();

            var testSorted = xml2.ToList();
            testSorted.Sort();

            success = new string(sortedExpected.ToArray()).Equals(new string(testSorted.ToArray()));

            Console.WriteLine("Match? " + success);
            Console.ReadKey();

        }
    }
}