I am reading in a bunch of XML files, transforming them and loading the data in to another system.
Previously I had done this using ThreadPool, however the provider of the files and therefore the structure has changed, so I'm now trying Aysync-Await and getting an odd result.
As I process the files I get a list of the xmlNodes and loop over them
foreach (XmlNode currentVenue in venueNodes)
{
      Console.WriteLine(currentVenue.OuterXml);
      Console.WriteLine(currentVenue.SelectSingleNode(@"//venueName").InnerText);
}
however the second WriteLine always returns the result expected for the first node, example:
<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 & Art Gallery</venueName></venue>
Artrix
here is the complete code:
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);
     }
 }
Obviously I've missed something, but I cannot see what, can someone point it out please?
SelectSingleNode returns only a single node in document order from the document. @jbl is correct, //venueName starts from the document root. The // xpath operator is the "descendent selector" operator.
I work with XML and XPath often and this is a common mistake. You need to make sure that your context  node is correct when calling SelectSingleNode. So, like we just all said, using //venueName gets the first <venueName /> node in document order starting from the root of the document.
In order to get the <venueName /> node that is a child of the current node you're iterating over, you need to use the following code:
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.
}
That should solve your problem.
Doesn't //venueName search from the document root ? 
I guess that, combined with SelectSingleNode, will always end-up on the same resulting  node (the first venueName node of the document)
You may try replacing //venueName with venueName
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With