2013-05-20 53 views
2

我讀了一堆的XML文件,轉化他們,到另一個系統加載數據相同的值。xmlNode.SelectSingleNode總是返回即使節點改變

以前我做了這個使用線程池,但文件的供應商,因此,結構發生了變化,所以現在我想Aysync,等待並得到一個奇怪的結果。

當我處理的文件,我得到的將XMLNode和循環名單在他們

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); 
    } 
} 

顯然我錯過了一些東西,但我可以看不清楚,請問有人能指出來嗎?

+0

沒有理由讓'processFile()''async'。你應該得到一個警告。另外,並行處理文件可能不會給你任何性能改善。 – svick

回答

5

SelectSingleNode返回更換//venueName相同結果節點(該文件的第一venueName節點)上,結合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. 
} 

這應該解決您的問題。

+0

謝謝大家,我將接受這個答案,因爲它更詳細,並希望將來可以幫助其他人。我認爲在節點父文檔上下文中執行節點對象上的方法是非直觀的。它就像string [1] .Contains(「apple」)搜索整個數組而不是索引1處的字符串。很奇怪。 – Stuart

+1

我同意你這是'SelectSingleNode'部分的意外行爲。和你一樣,我起初認爲該方法足夠聰明,可以將上下文節點設置爲調用該方法的節點。一點都不直觀。爲了讓人產生懷疑,也許這與Xpath規範有關...... – fourpastmidnight

1

是否從文檔根不//venueName搜索?

我猜

你可以嘗試用venueName

+0

是//確實從文檔根目錄搜索,但是在這種情況下該文件只是一個在已提取 – Stuart

+1

@Stuart它不喜歡的工作節點。你擁有的'XmlNode'仍然與整個文檔鏈接,你沒有「提取」它或類似的東西。 – svick

相關問題