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();
}
}
}
我的问题很简单。我正在使用 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();
}
}
}