[英]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.Value
和a.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.