linq to xml 枚举后代

发布于 2024-10-12 07:10:05 字数 1114 浏览 2 评论 0 原文

您好,尝试从我读过的教程中编写一个简单的 linq 查询。但我似乎无法让它发挥作用。我试图显示附加的 xml 文档中的两个地址,但只能显示第一个。有人可以帮我弄清楚为什么两者都没有被打印吗?非常感谢

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

Hi trying to write a simple linq query from a tutorial I read. But i cannot seem to get it to work. I am trying to display both the address in the attached xml document, but can only display the first one. Can someone help me figure out why both aren't being printed. Thank you very much

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

潦草背影 2024-10-19 07:10:05

您当前的查询返回 List>。这意味着您需要两个嵌套的 foreach 循环:一个用于循环列表,另一个用于循环 IEnumerable 的内容。

相反,您可以更新 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")) _

此查询所有 节点,并且仅匹配具有 < em>group “FooBar”的属性值。

第二:

From addr In email.Element("EmailTo").Descendants("Address") _
Select addr.Value

这是一个子查询,在第一部分(上面)结束的地方继续。它本质上是一种进一步查询原始查询结果的方法。在这里,我们查询所有

节点,最后为节点的内部文本选择它们的 Value。我们需要这样做的原因是 Descendants("Address") 返回一个包含所有“Address”元素的 IEnumerable。我们需要执行额外的查询(或 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 进行循环的额外工作。原始查询比 query1/query2 更清晰,但我编写它们只是为了澄清这一点。

Your current query returns a List<IEnumerable<XElement>>. That means you need two nested foreach loops: one to loop over the list, and another to loop over the content of the IEnumerable<XElement>.

Instead, you could update your LINQ query to use the Enumerable.SelectMany method and get to the addresses directly. In query format a SelectMany is represented by using a second from clause to indicate a subquery. This would resemble the following:

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

Also, the ToList isn't needed if you only want to iterate over the results and don't intend to use the result as a list for other purposes.

EDIT: to explain how this query works let's break it down in 2 parts:

First:

From email In emailList.Descendants("Email") _
Where (email.Attribute("group").Value.Equals("FooBar")) _

This queries for all <Email> nodes and only matches the ones that have a group attribute value of "FooBar".

Second:

From addr In email.Element("EmailTo").Descendants("Address") _
Select addr.Value

This is a subquery that continues where the first part (above) ended. It essentially is a way to further query the results of the original query. Here we query for all <Address> nodes and, finally, select their Value for the inner text of the nodes. The reason we need to do this is because Descendants("Address") returns a IEnumerable<XElement> containing all "Address" elements. We need to perform an additional query (or foreach) to iterate over those values and extract their values.

Another way to illustrate this is by breaking it down in 2 queries:

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

Notice the use of SelectMany in query2. The Select in query2 is that additional effort to loop over the IEnumerable that I mentioned earlier. The original query is clearer than query1/query2, but I wrote them just to clarify the point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文