2013-05-20 2 views
2

XML 파일을 변환하여 다른 시스템에로드하는 중입니다.xmlNode.SelectSingleNode는 노드가 변경 되더라도 항상 동일한 값을 반환합니다.

이전에 ThreadPool을 사용하여이 작업을 수행했지만 파일 제공 업체와 구조가 변경되어 이제는 Aysync-Await을 시도하고 이상한 결과가 나타납니다. 나는 파일을 처리하는 것처럼

나는 그 위로 된 XMLNodes 및 루프의 목록을

두 번째를 WriteLine은 항상 첫 번째 노드, 예를 들어, 예상되는 결과를 반환하지만
foreach (XmlNode currentVenue in venueNodes) 
{ 
     Console.WriteLine(currentVenue.OuterXml); 
     Console.WriteLine(currentVenue.SelectSingleNode(@"//venueName").InnerText); 
} 

:

<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 /> 노드를 가져옵니다.

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

문제를 해결해야한다 : 당신이 이상 반복하고있는 현재 노드의 자식 인 <venueName /> 노드를 얻기 위하여

, 다음과 같은 코드를 사용합니다.

+0

감사합니다 얘들 아, 나는이 답변을보다 자세하게 받아 들일 것이며 앞으로 다른 사람들을 도울 것입니다. 노드 객체에 대한 메소드를 노드 부모 문서 컨텍스트에서 실행하는 것이 비 직관적이라고 생각합니다. 그것은 문자열 [1] .Contains ("apple")와 같아서 인덱스 1에서 문자열 대신 전체 배열을 검색합니다. 이상한. – Stuart

+1

나는 이것이 'SelectSingleNode'의 일부에서 예기치 않은 행동을하는 것에 동의합니다. 여러분과 마찬가지로, 처음에는 메소드가 호출 될 노드에 문맥 노드를 설정할만큼 현명한 방법이라고 생각했습니다. 별로 직관적이지 않습니다. 의심의 이익을주기 위해서, 아마도 Xpath 스펙과 관련이있다. – fourpastmidnight

1

//venueName 문서 루트에서 검색 하시겠습니까?

나는 당신이 venueName

+0

예 // 문서의 루트에서 검색합니다. 그러나이 경우 문서는 추출 된 노드 중 하나입니다. – Stuart

+1

@Stuart 이렇게 작동하지 않습니다. 당신이 가지고있는'XmlNode'는 여전히 전체 문서에 링크되어 있습니다, 당신은 그것을 추출하지 않았습니다. – svick

관련 문제