2011-03-18 73 views
0

編輯:這是我試圖解析的示例XML文檔:http://us.battle.net/wow/en/forum/1011699/(查看源代碼)。LINQ to XML Multiple Selects

這裏有我想要檢索的項目:

  • 標題(TBODY/TR/TD/A)
  • 作者(TBODY/TR/TD)
  • 網址(也存儲在作者節點)
  • 日期(TBODY/TR/TD/DIV/DIV)
  • 回覆(TBODY/TR/TD)
  • 視圖(也存儲在上述節點)

我做了「前查詢」,所以我不必爲遠了每個以下查詢遍歷:

var threads = 
    from allThreads in xmlThreadList.Descendants(ns + "tbody") 
            .Descendants(ns + "tr") 
            .Descendants(ns + "td") 
    select allThreads; 

我代表論壇主題列表的XML文檔。在每個線程中都有不同的孩子,他們擁有我想要檢索的不同信息。目前我通過多次查詢XML文檔來做到這一點。有沒有辦法在單個查詢中提取這些信息並將其存儲在IEnumerable中?我現在這樣做的方式似乎效率低下。

// array of xelements that contain the title and url 
    var threadTitles = 
     (from allThreads in threads.Descendants(ns + "a") 
     where allThreads.Parent.Attribute("class").Value.Equals("post-title") 
     select allThreads).ToArray(); 

    // array of strings of author names 
    var threadAuthors = 
     (from allThreads in threads 
     where allThreads.Attribute("class").Value.Equals("post-author") 
     select allThreads.Value.Trim()).ToArray(); 

    // ... 
    // there are several more queries like this 
    // ... 

    // for loop to populate a list with all the extracted data 
    for (int i = 0, j = 0; i < threadTitles.Length; i++, j++) 
    { 
     ThreadItem threadItem = new ThreadItem(); 

     threadItem.Title = threadTitles[i].Value.Trim(); 
     threadItem.Author = threadAuthors[i]; 
     threadItem.Url = Path.Combine(_url, threadTitles[i].Attribute("href").Value); 
     threadItem.Date = threadDates[i]; 
     threadItem.Replies = threadRepliesAndViews[j++]; 
     threadItem.Views = threadRepliesAndViews[j]; 
     _threads.Add(threadItem); 
    } 

任何意見,將不勝感激。我是全新的LINQ to XML場景。

+0

能否請您提供您正在訪問的XML的例子嗎?請說明您想要提取的信息。 :) – 2011-03-18 14:57:39

+0

我已經發布了一些更多信息,讓我知道如果您需要更多 - 謝謝! – johnhforrest 2011-03-18 15:37:07

+0

你能告訴我們什麼在線程變量? – GreyCloud 2011-03-18 15:37:21

回答

2

希望這有助於:

string ns = "{http://www.w3.org/1999/xhtml}"; 

var doc = XDocument.Load("http://us.battle.net/wow/en/forum/1011699/"); 
var threads = from tr in doc.Descendants(ns + "tbody").Elements(ns + "tr") 
       let elements = tr.Elements(ns + "td") 
       let title = elements.First(a => a.Attribute("class").Value == "post-title").Element(ns + "a") 
       let author = elements.First(a => a.Attribute("class").Value == "post-author") 
       let replies = elements.First(a => a.Attribute("class").Value == "post-replies") 
       let views = elements.First(a => a.Attribute("class").Value == "post-views") 
       select new 
       { 
        Title = title.Value.Trim(), 
        Url = title.Attribute("href").Value.Trim(), 
        Author = author.Value.Trim(), 
        Replies = int.Parse(replies.Value), 
        Views = int.Parse(views.Value) 
       }; 

foreach (var item in threads) 
{ 
    Console.WriteLine(item); 
} 

Console.ReadLine(); 
+0

很好,謝謝! – johnhforrest 2011-03-18 16:32:54

1

嘗試像

from thread in threads 
select new ThreadItem() { 
    Title = thread.Descendants(ns + "a").First(title => title.Parent.Attribute("class").Value.Equals("post-title")), 
    Date = date query part 

    ect.... 
} 

這是你不一次又一次地解析整個XML塊將獲得一定的速度,而不是你只是通過每個小螺紋看幾次,每次提取不同的信息。

我很想知道哪些結果更快,因爲您正在有效交換整個元素項目適合緩存的希望,從而讓您在執行所有小查詢時能夠快速訪問它,希望(在您的舊代碼中)您的cpu上的分支預測器將調諧到每個長查詢,以提供更好的速度。

+0

我會仔細研究這個問題並回復給您,謝謝 – johnhforrest 2011-03-18 15:52:58

+0

上面我使用了AS-CII的答案,經過幾次比較,他們的平均時間大致相同,但它只是在一次調用中就乾淨得多。比我這樣做的方式 – johnhforrest 2011-03-18 16:31:56