2013-07-09 54 views
1

我使用的後續代碼讀取XML文件的XML文件的最後n個元素:閱讀使用LINQ的XDocument

XDocument doc = XDocument.Load(xmlPath); 

     foreach (var node in doc.Descendants("LogInfo")) 
     { 

      ListViewItem item = new ListViewItem(new string[] 
      { 
       node.Element("MailBox").Value, 
       node.Element("LastRun").Value, 
      }); 
      listViewHome.Items.Add(item); 
     } 

我怎樣才能改變這種代碼,以接收元素剛剛過去的「n」個從那個XML文件? 在此先感謝。

回答

7

你可以這樣做:

var nodes = doc.Descendants("LogInfo"); 
foreach (var node in nodes.Skip(Items.Count() - n)) 
{ 
    ... 
} 

或者這樣:

var nodes = doc.Descendants("LogInfo"); 
foreach (var node in nodes.Reverse().Take(n).Reverse()) 
{ 
    ... 
} 

如果你喜歡冒險的感覺,你也可以寫自己的extension method這應該是比任一更有效。這裏是我的快速和骯髒的解決方案:

public static IEnumerable<T> TakeFromEnd<T>(this IEnumerable<T> items, int n) 
{ 
    var arry = new T[n]; 
    int i = 0; 
    foreach(var x in items) 
    { 
     arry[i++ % n] = x; 
    } 

    if (i < n) 
    { 
     n = i; 
     i = 0; 
    } 

    for (int j = 0; j < n; j++) 
    { 
     yield return arry[(i + j) % n]; 
    } 
} 

var nodes = doc.Descendants("LogInfo"); 
foreach (var node in nodes.TakeFromEnd(n)) 
{ 
    ... 
} 
+1

+1好的技巧與反向 –

+0

+1。我有兩個答案的唯一問題是'Count()'會遍歷一次,'Skip()。另一次採取()'。雖然LINQ很好地表達了這個問題,但它並不是最理想的答案。 –

+0

@pswg假設你有10個項目,但想要最後3個,Reverse將遍歷全部10個,然後最後3個遍歷兩次(所以這是'Count + 2 * Take')。如果你跳過(Count() - Take)',你可以遍歷10個Count和另外10個(Skip的'7','Take'的3個)。我認爲Reverse可能更有效,但由於它全部在內存中,所以差別不會很明顯。 –

3
XDocument doc = XDocument.Load(xmlPath); 
var logs = doc.Descendants("LogInfo"); 
var logsCount = logs.Count(); 

foreach (var node in logs.Skip(logsCount - n).Take(n)) 
{ 
    ListViewItem item = new ListViewItem(new string[] 
    { 
     node.Element("MailBox").Value, 
     node.Element("LastRun").Value, 
    }); 
    listViewHome.Items.Add(item); 
} 

這裏是XPath的解決方案,這將枚舉XML一旦

var xpath = String.Format("//LogInfo[position()>last()-{0}]", n); 
foreach (var log in doc.XPathSelectElements(xpath)) 
{ 
    ListViewItem item = new ListViewItem(new string[] 
    { 
     (string)log.Element("MailBox"), 
     (string)log.Element("LastRun") 
    }); 
    listViewHome.Items.Add(item); 
} 
+2

嗯,XPath解決方案的+1。有一段時間沒有看到那些人。 –

+0

我試着用XPath解決方案,但是我沒有收到任何數據......列表視圖是空的... – Simon

+0

@Simon剛剛通過驗證,它的工作原理沒有問題。確保你在那個名字空間中定義的文件的頂部有'使用System.Xml.XPath;' –