Linq to Xml: выбор элементов, если значение атрибута равно значению узла в IEnumerable <XElement> - PullRequest
8 голосов
/ 22 февраля 2009

Я создаю объект IEnumerable, который просто содержит нужные мне узлы из XML-файла:

IEnumerable<XElement> rosters = XDocument.Load("roster.xml")
                                         .Elements("rosterlist")
                                         .Elements("roster")
                                         .Where(w => w.Element("division")
                                                      .Value
                                                      .Equals("SUPER AWESOME DIVISION"));

Итак, это коллекция из них:

<rosterlist>
    <roster>
        <userid>1</userid>
        <name></name>
        <etc></etc>
    </roster>
    <roster>
        <userid>2</userid>
        <name></name>
        <etc></etc>
    </roster>
</rosterlist>

Я хочу получить только тех пользователей, у которых атрибут userid также является узлом userid в коллекции rosters.

IEnumerable<XElement> users = XDocument.Load("user.xml")
                                       .Elements("userlist")
                                       .Elements("user")
                                       .Where(w => rosters.Elements("userid")
                                                          .Contains(w.Attribute("userid").Value));

Но это дает мне ошибку:

Аргументы типа для метода 'System.Linq.Enumerable.Contains (System.Collections.Generic.IEnumerable, TSource)' не могут быть получены из использования. Попробуйте указать аргументы типа явно.

Что не так с моим подходом?

1 Ответ

6 голосов
/ 22 февраля 2009

Одна проблема, которую я вижу, заключается в том, что в последнем фрагменте кода ...Elements("userid") возвращает список объектов XElement, которые не могут содержать строку, возвращаемую свойством Value. Это должно работать ...

IEnumerable<XElement> rosters = obRoot.Elements("rosterlist").Elements("roster");
var rosterUserIds = (rosters.Elements("userid").Select(r => r.Value));
IEnumerable<XElement> users = obRoot.Elements("userlist").Elements("user")
                .Where(u => rosterUserIds.Contains(u.Attribute("userid").Value));

Однако я бы сделал это с помощью запроса на присоединение. Выберите списки пользователей для присоединения по идентификатору пользователя
Было бы что-то вроде этого

string sXml = @"
<root>
<rosterlist>
    <roster>
        <userid>1</userid>
        <name>R1</name>
        <etc></etc>
    </roster>
    <roster>
        <userid>2</userid>
        <name>R2</name>
        <etc></etc>
    </roster>
</rosterlist>
<userlist>
    <user userid='1'>
        <name>User on roster</name>
    </user>
    <user userid='5'>
        <name>User not on roster</name>
    </user>
</userlist>
</root>

";

XElement obRoot = XElement.Parse( sXml );
var results = from user in obRoot.Elements("userlist").Elements("user")
   join roster in obRoot.Elements("rosterlist").Elements("roster")
   on user.Attribute("userid").Value equals roster.Element("userid").Value
   select new {Name=user.Element("name").Value, RosterName=roster.Element("name").Value} ;

foreach (var v in results)
{
   Console.WriteLine("{0, -20} on Roster {1, -20}", v.Name, v.RosterName);
}

Выходы:

User on roster       on Roster R1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...