即使节点发生更改,xmlNode.SelectSingleNode也始终返回相同的值

时间:2013-05-20 13:26:05

标签: c# xml

我正在阅读一堆XML文件,转换它们并将数据加载到另一个系统。

以前我使用ThreadPool完成了这个,但是文件的提供者因此结构发生了变化,所以我现在正在尝试Aysync-Await并得到一个奇怪的结果。

当我处理文件时,我得到一个xmlNodes列表并循环它们

foreach (XmlNode currentVenue in venueNodes)
{
      Console.WriteLine(currentVenue.OuterXml);
      Console.WriteLine(currentVenue.SelectSingleNode(@"//venueName").InnerText);
}

但是第二个WriteLine总是返回第一个节点的预期结果,例如:

<venue venueID="xartrix" lastModified="2012-08-20 10:49:30"><venueName>Artrix</venueName></venue>
Artrix
<venue venueID="xbarins" lastModified="2013-04-29 11:39:07"><venueName>The Barber Institute Of Fine Arts, University Of Birmingham</venueName></venue>
Artrix
<venue venueID="xbirmus" lastModified="2012-11-13 16:41:13"><venueName>Birmingham Museum &amp; Art Gallery</venueName></venue>
Artrix

这是完整的代码:

public async Task ProcessFiles()
{
    string[] filesToProcess = Directory.GetFiles(_filePath);
    List<Task> tasks = new List<Task>();

    foreach (string currentFile in filesToProcess)
    {
        tasks.Add(Task.Run(()=>processFile(currentFile)));
    }

    await Task.WhenAll(tasks);

}

private async Task processFile(string currentFile)
{
    try
    {
         XmlDocument currentXmlFile = new XmlDocument();
         currentXmlFile.Load(currentFile);

         //select nodes for processing
         XmlNodeList venueNodes = currentXmlFile.SelectNodes(@"//venue");

         foreach (XmlNode currentVenue in venueNodes)
         {
              Console.WriteLine(currentVenue.InnerXml);
              Console.WriteLine(currentVenue.SelectSingleNode(@"//venueName").InnerText);                 
         }
     }
     catch (Exception e)
     {
         Console.WriteLine(e.Message);
     }
 }

显然我错过了一些东西,但我看不清楚,有人能说出来吗?

2 个答案:

答案 0 :(得分:7)

SelectSingleNode仅从文档中按文档顺序返回单个节点。 @jbl是正确的,//venueName从文档根开始。 // xpath运算符是“后代选择器”运算符。

我经常使用XML和XPath,这是一个常见的错误。调用SelectSingleNode时,您需要确保您的上下文节点是正确的。因此,就像我们刚才所说的那样,使用//venueName从文档的根开始按文档顺序获取第一个<venueName />节点。

为了获得您正在迭代的当前节点的子节点<venueName />节点,您需要使用以下代码:

foreach (XmlNode currentVenue in venueNodes)
{
    Console.WriteLine(currentVenue.OuterXml);
    Console.WriteLine(currentVenue.SelectSingleNode(@".//venueName").InnerText); // The '.' means from the current node. Without it, searching starts from the document root, not currentVenue.
}

这应该可以解决你的问题。

答案 1 :(得分:1)

//venueName是否从文档根目录中搜索?

我想,结合SelectSingleNode,总是会在同一结果节点(文档的第一个venueName节点)上结束。

您可以尝试将//venueName替换为venueName