使用 LINQ 从 XDocument 检索嵌套列表

本文关键字:嵌套 列表 检索 XDocument LINQ 使用 | 更新日期: 2023-09-27 18:37:26

好的,我希望我的链接查询返回用户列表。下面是 XML

<section type="Users">
    <User type="WorkerProcessUser">
        <default property="UserName" value="Main"/>
        <default property="Password" value=""/>
        <default property="Description" value=""/>
        <default property="Group" value=""/>
    </User>
    <User type="AnonymousUser">
        <default property="UserName" value="Second"/>
        <default property="Password" value=""/>
        <default property="Description" value=""/>
        <default property="Group" value=""/>
    </User>
</section>

而我当前不起作用的 LINQ 查询.doc是一个 XDocument

var users = (from iis in doc.Descendants("section")
                     where iis.Attribute("type").Value == "Users"
                     from user in iis.Elements("User")
                     from prop in user.Descendants("default")
                     select new 
                     {
                         Type = user.Attribute("type").Value, 
                         UserName = prop.Attribute("UserName").Value
                     });

我得到了一个Object reference not set to an instance of an object例外。谁能告诉我我需要修复什么?

这是我修复错误属性名称后的第二次尝试。但是,当我尝试使用它或至少当我尝试将其写入控制台时,这个似乎没有为我枚举用户名值。此外,这总共返回 8 个结果,我应该只有 2 个结果,因为我只有 2 个用户。

(from iis in doc.Descendants("section")
                     where iis.Attribute("type").Value == "Users"
                     from user in iis.Elements("User")
                     from prop in user.Descendants("default")
                     select new
                     {
                         Type = user.Attribute("type").Value,
                         UserName = (from name in prop.Attributes("property")
                                     where name.Value == "UserName"
                                     select name.NextAttribute.Value).ToString()
                     });

使用 LINQ 从 XDocument 检索嵌套列表

我会做这样的事情:

doc.XPathSelectElement("section[@type='Users']")
.Elements("User")
.Select(c => new
{
    Type = c.Attribute("type").Value,
    UserName = c.XPathSelectElement("default[@property='UserName']").Attribute("value").Value
});

您需要在.cs文件的顶部添加using System.Xml.XPath;,以便找到XPathSelectElement扩展方法。

您的default元素没有 username 属性,usernameproperty 属性的值。

以下是您的查询应该如何作为Henk Holterman所写内容的替代方案。不同之处在于我在User元素级别而不是default[@property='UserName']元素级别进行选择

var usr = (from iis in doc.Descendants("section")
           where iis.Attribute("type").Value == "Users"
           from user in iis.Elements("User")
           select new
           {
               Type = user.Attribute("type").Value,
               UserName = (from prop in user.Descendants("default")
                           where prop.Attribute("property").Value == "UserName"
                           select prop.Attribute("value").Value).FirstOrDefault()
           });

与第二次尝试相比,代码from prop in user.Descendants("default")已移至匿名类型构造函数中,并且简化了对用户名的分配。

var root = XDocument.Load(@"...").Root;
var ns = root.GetDefaultNamespace();
var users = root.Descendants(ns.GetName("default")).Where(e => e.Attribute("property").Value == "UserName").Select(e => new
{
    Type = e.Parent.Attribute("type").Value,
    UserName = e.Attribute("value").Value
});
Console.WriteLine(String.Join(Environment.NewLine, users.Select(u => String.Format("{0} ({1})", u.UserName, u.Type))));