2011-01-13 50 views
1

嗨,试图从我读的教程写一个简单的linq查询。但我似乎无法得到它的工作。我试图在附加的xml文档中显示这两个地址,但只能显示第一个。有人能帮我弄清楚为什么两者都没有被打印。非常感谢linq to xml enumerating over descendants

<?xml version="1.0" encoding="utf-8" ?> 
<Emails> 
    <Email group="FooBar"> 
    <Subject>Test subject</Subject> 
    <Content>Test Content</Content> 
    <EmailTo> 
     <Address>[email protected]</Address> 
     <Address>[email protected]</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 

回答

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

注意在query2使用SelectManyquery2中的Select是额外的努力来循环我前面提到的IEnumerable。原始查询比查询1 /查询2更清晰,但是我只是为了澄清这一点而写了它们。

+0

我没有完全理解你的linq语句是如何工作的。你可以为我分解它还是指向我可以阅读的一些资源。我不理解的是第二个从句。这是如何给我我需要的。感谢您的回答和帮助 – gh9 2011-01-13 15:56:33