2013-03-28 20 views
0

我有一個XML結構,我解析,並返回作爲一個IEnumerable:如何使用linq查找list/IEnumerable中的子元素?

public static class XmlConverter 
{ 

    public static IEnumerable<MenuItem> Parser() 
    { 
     using (var fileStream = new FileStream(HttpContext.Current.Server.MapPath("~/DataSource/MenuNavigation.xml"), FileMode.Open)) 
     { 
      return Read(fileStream); 
     } 
    } 

    private static IEnumerable<MenuItem> Read(Stream stream) 
    { 
     return (IEnumerable<MenuItem>)XmlSerializer().Deserialize(stream); ; 
    } 


    private static XmlSerializer XmlSerializer() 
    { 
     return new XmlSerializer(typeof(List<MenuItem>), GetXmlRootAttribute()); 

    } 

    private static XmlRootAttribute GetXmlRootAttribute() 
    { 
     return new XmlRootAttribute() { ElementName = "Navigation", IsNullable = true }; 
    } 
} 

它被解析到這個對象:

public class MenuItem 
{ 
    [XmlAttribute("Id")] 
    public int Id { get; set; } 
    [XmlAttribute("Name")] 
    public string Name { get; set; } 
    [XmlAttribute("Description")] 
    public string Description { get; set; } 
    [XmlAttribute("Link")] 
    public string Link { get; set; } 
    [XmlAttribute("Role")] 
    public string RoleId { get; set; } 
    [XmlAttribute("Alert")] 
    public string Alert { get; set; } 
    [XmlElement("Criterion")] 
    public List<Criterion> Criteria { get; set; } 

    private List<MenuItem> _menuItems = new List<MenuItem>(); 

    [XmlElement("MenuItem")] 
    public MenuItem[] MenuItems 
    { 
     get { return _menuItems.ToArray(); } 
     set 
     { 
      _menuItems.Clear(); 
      if (value != null) 
      { 
       _menuItems.AddRange(value); 
      } 
     } 
    } 
} 

<menuItem Id="1"> 
     <menuItem Id="2"> 
      <menuItem Id="5"> 
        <menuItem Id="9"> 
         <criterion></criterion> 
        </menuItem> 
      </menuItem> 
     </menuItem> 
    </menuItem> 
    <menuItem Id="10> 
    /// huge xml document from here on... 

我使用這個類解析它

當我在IEnumerable上進行Linq查詢時,我使用:

var criteria = menuItems.Where(x => x.Id == menuItem.Id) 
         .Select(x => x.Criteria) 
         .FirstOrDefault(); 

問題是IEnumerable這裏只有14個項目。那些父項目,所以如果我正在尋找id == 9,那麼它不會被發現,因爲它是Id 1的子元素。

如何編輯上面的linq語句,以便它檢查每個級別名爲menuItem的元素,而不僅僅是相關Id的父母?

更新:

了IEnumerable看起來是這樣的:

Count=14 
+MenuItem //nested menuItem 
    Name 
+0

你怎麼分析呢?包含代碼。 –

+0

你的MenuItem類是什麼樣的?它如何代表其子女? (你真的有一個4層深的菜單結構嗎?) –

+0

不幸的是,我的客戶要求它在某些地方是6深。現在發佈我的MenuItem類 – Robert

回答

1

你可以先flatten層次(LINQ本身不具有任何支持) - 然後你在做什麼。

例如How do I select recursive nested entities using LINQ to Entity

...然後

var item = menuItems.Flatten(y => y.MenuItems).Where(x => x.Id == 5) 
    .FirstOrDefault(); 
+0

我會研究。我真的希望Linq有一些內置的魔法 – Robert

+0

我不這麼認爲 - 你不會失去太多 - 它會列舉 - 直到它找到一個 - 唯一的問題可能是你想要的順序,深度 - 首先等你可以調整我猜。 – NSGaga

+0

由於我使用的是Xml,並且文檔不是一百萬行,所以它會以很快的速度在列表中移動。我主要得到的代碼基於他的例子 – Robert

相關問題