你试着从我读过的教程中写一个简单的linq查询。但我似乎无法让它发挥作用。我试图在附加的xml文档中显示两个地址,但只能显示第一个。有人可以帮我弄清楚为什么两个都不打印。非常感谢你
<?xml version="1.0" encoding="utf-8" ?>
<Emails>
<Email group="FooBar">
<Subject>Test subject</Subject>
<Content>Test Content</Content>
<EmailTo>
<Address>foo@bar.com</Address>
<Address>bar@foo.com</Address>
</EmailTo>
</Email>
</Emails>
Dim steve = (From email In emailList.Descendants("Email") _
Where (email.Attribute("group").Value.Equals("FooBar")) _
Select content = email.Element("EmailTo").Descendants("Address")).ToList()
If Not steve Is Nothing Then
For Each addr In steve
Console.WriteLine(addr.Value)
Next
Console.ReadLine()
End If
答案 0 :(得分:2)
您当前的查询返回List<IEnumerable<XElement>>
。这意味着您需要两个嵌套的foreach
循环:一个循环遍历列表,另一个循环遍历IEnumerable<XElement>
的内容。
相反,您可以更新LINQ查询以使用Enumerable.SelectMany
方法并直接访问地址。在查询格式中,SelectMany
通过使用第二个from
子句来表示子查询。这将类似于以下内容:
Dim query = (From email In emailList.Descendants("Email") _
Where (email.Attribute("group").Value.Equals("FooBar")) _
From addr In email.Element("EmailTo").Descendants("Address") _
Select addr.Value).ToList()
If query.Any() Then
For Each addr In query
Console.WriteLine(addr)
Next
End If
此外,如果您只想迭代结果并且不打算将结果用作其他目的的列表,则不需要ToList
。
编辑以解释此查询的工作方式,让我们将其细分为两部分:
首先:
From email In emailList.Descendants("Email") _
Where (email.Attribute("group").Value.Equals("FooBar")) _
此查询所有<Email>
个节点,仅匹配组属性值为“FooBar”的节点。
第二
From addr In email.Element("EmailTo").Descendants("Address") _
Select addr.Value
这是一个子查询,它继续在第一部分(上面)结束的地方。它本质上是一种进一步查询原始查询结果的方法。在这里,我们查询所有<Address>
个节点,最后,为节点的内部文本选择它们的Value
。我们需要这样做的原因是因为Descendants("Address")
返回包含所有“地址”元素的IEnumerable<XElement>
。我们需要执行一个额外的查询(或foreach
)来迭代这些值并提取它们的值。
另一种说明这种方法的方法是在2个查询中将其分解:
Dim query1 = From email In emailList.Descendants("Email") _
Where (email.Attribute("group").Value.Equals("FooBar"))
Select email.Element("EmailTo").Descendants("Address")
Dim query2 = query1.SelectMany(Function(addr) addr.Select(Function(a) a.Value))
请注意SelectMany
中使用query2
。 Select
中的query2
是我在前面提到的IEnumerable
循环的额外工作。原始查询比query1 / query2更清晰,但我写这些只是为了澄清这一点。