2009-10-06 55 views
1

我正在創建一個動態的XML導航菜單,它由MenuItem和SubMenuItem(兩個類)組成。我想解析下面的XML並使用LINQ來解析它並檢索數據。嵌套的Linq創建多個類對象

這裏是一個示例XML:

<?xml version="1.0" encoding="utf-8" ?> 

<MenuItems> 
    <Item Id="1" Url="Default.aspx" LinkText="Home" Description="Test Description" Target=""> 
    <SubItem Id="1" ParentId="1" Url="Default.aspx" LinkText="SubMenu1" Description="Test Description" Target="" /> 
    <SubItem Id="2" ParentId="1" Url="Default.aspx" LinkText="SubMenu2" Description="Test Description" Target="" /> 
    <SubItem Id="3" ParentId="1" Url="Default.aspx" LinkText="SubMenu3" Description="Test Description" Target="" /> 
    </Item> 
    <Item Id="2" Url="Default2.aspx" LinkText="Menu2" Description="Test Description" Target="" /> 
    <Item Id="3" Url="Default3.aspx" LinkText="Menu3" Description="Test Description" Target="" /> 
</MenuItems> 

我想使用LINQ,但我有與語法的麻煩。你可以使用嵌套的LINQ查詢來填充兩個對象列表,如下所示?

List<MenuItem> MenuItems = null; 
try 
{ 
    XElement xmlDoc = XElement.Load(xmlPath + xmlFileName); 
    if (xmlDoc != null) 
    { 
     MenuItems = 
       (from menuItem in xmlDoc.Descendants("Item") 
       select new MenuItem 
       { 
        Id = menuItem.Attribute("Id").Value, 
        Description = menuItem.Attribute("Description").Value, 
        LinkText = menuItem.Attribute("LinkText").Value, 
        Url = menuItem.Attribute("Url").Value, 
        Target = menuItem.Attribute("Description").Value, 
        SubMenuItems = (from subMenuItem in xmlDoc.Descendants("SubItem") 
            select new SubMenuItem 
            { 
             Id = menuItem.Attribute("Id").Value, 
             ParentId = menuItem.Attribute("ParentId").Value, 
             Description = menuItem.Attribute("Description").Value, 
             LinkText = menuItem.Attribute("LinkText").Value, 
             Url = menuItem.Attribute("Url").Value, 
             Target = menuItem.Attribute("Description").Value, 
            }).ToList<SubMenuItem>(), 
       }).ToList<MenuItem>(); 
    } 
} 

有人可以幫助LINQ解析這個XML到這兩個嵌套在另一個類中嗎?

public class MenuItem 
{ 
    public MenuItem() { } 

    private string id; 
    private string url; 
    private string linkText; 
    private string description; 
    private string target; 
    private List<SubMenuItem> subMenuItems = new List<SubMenuItem>(); 

    public string Id { get { return id; } set { id = value; } } 
    public string Url { get { return url; } set { url = value; } } 
    public string LinkText { get { return linkText; } set { linkText = value; } } 
    public string Description { get { return description; } set { description = value; } } 
    public string Target { get { return target; } set { target = value; } } 
    public List<SubMenuItem> SubMenuItems { get { return subMenuItems; } set { subMenuItems = value; } } 
} 

public class SubMenuItem 
{ 
    public SubMenuItem() { } 

    private string id; 
    private string parentid; 
    private string url; 
    private string linkText; 
    private string description; 
    private string target; 

    public string Id { get { return id; } set { id = value; } } 
    public string ParentId { get { return parentid; } set { parentid = value; } } 
    public string Url { get { return url; } set { url = value; } } 
    public string LinkText { get { return linkText; } set { linkText = value; } } 
    public string Description { get { return description; } set { description = value; } } 
    public string Target { get { return target; } set { target = value; } } 
} 

謝謝!

回答

1

我想你可以通過一些遞歸來解決這個問題。你可能只需要MenuItem而不是兩個類。它們基本相同。然後,如果你創建了一個SelectDecendants方法,它會繼續調用它來獲取當前節點的子節點。類似這樣的:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var doc = XDocument.Load("input.xml"); 
     var menuItems = SelectDescendants(doc.Elements("MenuItems").Elements()); 
    } 

    public static List<MenuItem> SelectDescendants(IEnumerable<XElement> menuItems) 
    { 
     return (from menuItem in menuItems 
        select new MenuItem 
        { 
         Id = menuItem.Attribute("Id").Value, 
         Description = menuItem.Attribute("Description").Value, 
         LinkText = menuItem.Attribute("LinkText").Value, 
         Url = menuItem.Attribute("Url").Value, 
         Target = menuItem.Attribute("Description").Value, 
         SubMenuItems = SelectDescendants(menuItem.Elements()).ToList() 
        }).ToList(); 
    } 

} 
+0

我有一些麻煩的這句法工作。 linq查詢似乎不理解語法。你能澄清一下,我怎麼直接用XElement menuItem來使用linq? – kazzamalla 2009-10-06 19:07:33

+0

在這裏,我將它編碼在頭頂。上面的代碼現在已經過測試。希望能幫助到你。 – 2009-10-06 19:27:27

+0

謝謝!在使用測試代碼編輯之前,我得到了一個修改後的版本,然後使用您傳遞的測試代碼作爲參考。非常感謝您的時間! – kazzamalla 2009-10-06 19:41:34

2

如果你將邏輯隔離多一點,它可能會有所幫助。最好的選擇是IMO,它將爲構造函數添加一個接受XElement的MenuItem和SubMenuItem。

public class MenuItem 
{ 
    public MenuItem() { } 

    public MenuItem(XElement xmlDoc) 
    { 
     this.id = xmlDoc.Element("Id").Value; 
     this.url = xmlDoc.Element("Url").Value; 
     // etc. 
     subMenuItems = (from subMenuItem in xmlDoc.Descendants("SubItem") 
         select new SubMenuItem(subMenuItem)).ToList(); 

    // etc. 
} 

public class SubMenuItem 
{ 
    public SubMenuItem() { } 

    public SubMenuItem(XElement xmlDoc) 
    { 
     this.id = xmlDoc.Element("Id").Value; 
     // etc. 
    } 
    // etc. 
} 

那會清理您最初的選擇是:

MenuItems = (from menuItem in xmlDoc.Descendants("Item") 
      select new MenuItem(menuItem)).ToList(); 
+0

非常感謝您的幫助。我嘗試了兩種方法,將來會使用這個解決方案,我剛剛開始使用Jakers的方式,所以我選擇了這個方法。再次感謝! – kazzamalla 2009-10-06 19:40:37