使用LINQ从XDocument检索嵌套列表

时间:2012-06-15 19:30:02

标签: c# xml linq

好的,我希望我的链接查询返回用户列表。下面是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个例外。谁能告诉我我需要修理什么?

这是我修复错误的属性名称后的第二次尝试。但是,当我尝试使用它时,或者至少当我尝试将其写入控制台时,这个似乎不会为我枚举UserName值。此外,这将返回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()
                     });

3 个答案:

答案 0 :(得分:1)

我会做这样的事情:

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扩展方法。

答案 1 :(得分:0)

您的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")已被移动到匿名类型构造函数中,并且已经简化了对UserName的分配。

答案 2 :(得分:0)

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