Ваш текущий запрос возвращает 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
не требуется, если вы хотите перебирать результаты и не намерены использовать результат в качестве списка для других целей.
РЕДАКТИРОВАТЬ: чтобы объяснить, как работает этот запрос, давайте разбить его на 2 части:
Первый:
From email In emailList.Descendants("Email") _
Where (email.Attribute("group").Value.Equals("FooBar")) _
Опрашивает все <Email>
узлы и совпадает только с теми, которые имеют атрибут group атрибута "FooBar".
Второе:
From addr In email.Element("EmailTo").Descendants("Address") _
Select addr.Value
Это подзапрос, который продолжается там, где закончилась первая часть (выше). По сути, это способ дальнейшего запроса результатов исходного запроса. Здесь мы запрашиваем все <Address>
узлы и, наконец, выбираем их Value
для внутреннего текста узлов. Причина, по которой мы должны это сделать, заключается в том, что Descendants("Address")
возвращает IEnumerable<XElement>
, содержащий все элементы "Address". Нам нужно выполнить дополнительный запрос (или 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, но я написал их просто для пояснения.