【问题标题】:Xpath in C# : getting element out of a xml "list" (siblings)C# 中的 Xpath:从 xml“列表”(兄弟姐妹)中获取元素
【发布时间】:2015-04-05 17:12:12
【问题描述】:

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

看起来是这样的:

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>

我希望能够确保两个文件中“附加税”的内容相同(记住顺序并不重要),所以我尝试了这个:

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 循环不起作用。

比较以下两个最容易的是什么(这种比较的预期结果是“平等”)

<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>

谢谢

【问题讨论】:

  • 您的问题并不“简单”,而且指定得很差。你不能指望程序员根据这个问题的“规范”编写代码,它主要基于一个输入和输出的例子。

标签: c# xml select xpath


【解决方案1】:

这将满足您的需求,您可能需要针对您的真实对象进行更改,但这应该可以帮助您入门。我证明了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();

        }
    }
}

【讨论】:

  • 天真的方法非常有效,它会让我开始处理更复杂的事情! (我有同样的问题,但第一个属性不重要......)。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-27
  • 2019-08-21
  • 2020-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多