【问题标题】:Nested Linq to created multiple class objects嵌套 Linq 以创建多个类对象
【发布时间】:2009-10-06 18:01:54
【问题描述】:

我希望创建一个动态 XML 导航菜单,它由 MenuItem 和 SubMenuItem(两个类)组成。我想解析以下 XML 并使用 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; } }
}

谢谢!

【问题讨论】:

    标签: c# .net xml linq


    【解决方案1】:

    如果您将逻辑分离得更多一些,这可能会有所帮助。最好的办法是,IMO,向 MenuItem 和 SubMenuItem 添加一个接受 XElement 的构造函数。

    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();
    

    【讨论】:

    • 非常感谢您的帮助。我尝试了两种方式,将来会使用这个解决方案,我刚刚开始使用 Jakers 的方式,所以我选择了那个。再次感谢!
    【解决方案2】:

    我认为你可以通过一些递归来解决这个问题。您可能只有 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();
        }
    
    }
    

    【讨论】:

    • 我在让它的语法正常工作时遇到了一些麻烦。 linq 查询似乎不理解语法。你能澄清一下我如何直接将 linq 与 XElement menuItem 一起使用吗?
    • 给你,我从头顶编码。上面的代码现在已经过测试。希望对您有所帮助。
    • 谢谢!在您使用测试代码进行编辑之前,我得到了一个修改版本,然后使用您传递的测试代码作为参考。非常感谢您的宝贵时间!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多