繁体   English   中英

Linq to XML:使用元素属性和值创建一个匿名对象

[英]Linq to XML: create an anonymous object with element attributes and values

我是Linq的新手,正在尝试查询XML文档以查找特定用户的客户经理列表。 (我意识到将其放入数据库或其他内容可能更有意义,但是这种情况需要使用XML文档)。

<user emailAddress='user@fabrikam.com'>
    <accountManager department='Customer Service' title='Manager'>manager@fabrikam.com</accountManager>
    <accountManager department='Sales' title='Account Manager'>manager@fabrikam.com</accountManager>
    <accountManager department='Sales' title='Account Manager'>manager@fabrikam.com</accountManager>
</user>

我试图创建具有XElement属性(部门,标题)和值(电子邮件)组成的属性的对象列表(匿名类型?)。 我知道我可以两者兼得,但我的问题是两者都选。

这是我正在尝试的:

var managers = _xDoc.Root.Descendants("user")
               .Where(d => d.Attribute("emailAddress").Value == "user@fabrikam.com")
               .SelectMany(u => u.Descendants("accountManager").Select(a => a.Value));

foreach (var manager in managers)
{
     //do stuff
}

我可以在a.Valuea.Attribute ,但我无法弄清楚如何让两者并将其存储在一个对象。 我有一种感觉,它看起来像:

select new { 
    department = u.Attribute("department").Value,
    title = u.Attribute("title").Value,
    email = u.Value
};

你是对的。 看起来就像那样。

例如:

_xDoc.Root.Descendants("user")
          .Where(d => d.Attribute("emailAddress").Value == "user@fabrikam.com")
          .SelectMany(u => u.Descendants("accountManager"))
          .Select(a => new { 
              department = a.Attribute("department").Value,
              title = a.Attribute("title").Value,
              email = a.Value
          });

编辑 :使用查询理解语法:

from u in _xDoc.Root.Descendants("user")
where u.Attribute("emailAddress").Value == "user@fabrikam.com"
from a in u.Descendants("accountManager")
select new { 
               department = a.Attribute("department").Value,
               title = a.Attribute("title").Value,
               email = a.Value
           });

如果要从Select方法返回匿名类型,可以编写:

var managers = 
  _xDoc.Root.Descendants("user") 
       .Where(d => d.Attribute("emailAddress").Value == "user@fabrikam.com") 
       .SelectMany(u => 
          u.Descendants("accountManager")
           .Select(a => new {  
              Department = u.Attribute("department").Value, 
              Title = u.Attribute("title").Value, 
              Email = u.Value })
        );

创建匿名类型的语法并不直接绑定到select关键字。 您可以像这样使用它:

var manager = new { Department = "Somewhere", Title = "Mr" };

因此,语法a => new { ... }是返回新匿名类型的lambda表达式,就像select new { ... }是构造新匿名类型的子句一样。

关于在点符号和查询语法之间进行选择-这确实是个人喜好(尽管使用查询语法时某些情况看起来更好,并且诸如Count某些方法只能使用点符号来使用)。 但是,所有查询都由编译器转换为方法调用。

我假设只有一个用户sipAddress == sipUri

让我们从这个开始:

var managers = _xDoc.Root

您可以使用.First仅选择匹配的第一个元素.First

.First(d => d.Attribute("sipAddress").Value == sipUri)

这将使第一个用户谓词返回true。 然后,您需要将元素中的属性和值都提取到一个新对象(匿名类型)中。

如果有很多用户,并且您想要列出的所有经理,则可以使用.SelectMany (即,对于每个用户,有很多经理,选择所有经理)来完成此操作,但在这种情况下,我假设只有一个,并且.First已返回该元素,因此您只需使用其属性即可访问经理列表

.Descendants("accountManager")

然后,您将获得所有从选定元素降序的XElement 使用元素中的值将其转换为另一个对象是通过使用映射函数完成的,在Linq中是.Select

.Select(managerElem => new {
    department = u.Attribute("department").Value,
    title = u.Attribute("title").Value,
    email = u.Value 
});

如前所述,如果有多个用户使用正确的sipAddress并且您希望所有管理者,只需将.Descendants包装在.SelectMany

.SelectMany(userElem => userElem.Descendants("accountManager"))

我尚未测试过代码,但我相信您可以按照我写的内容弄清楚。

希望这可以帮助! :)随时在评论中询问您是否仍然感到困惑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM