Linq to Xml: memilih elemen jika nilai atribut sama dengan nilai node dalam IEnumerable‹XElement›

Saya membuat objek IEnumerable yang hanya berisi node yang saya inginkan dari file xml:

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

Jadi ini adalah kumpulan dari ini:

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

Saya hanya ingin mengambil pengguna yang atribut userid juga merupakan simpul userid dalam koleksi rosters.

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

Tapi itu memberi saya kesalahan:

Argumen tipe untuk metode 'System.Linq.Enumerable.Contains(System.Collections.Generic.IEnumerable, TSource)' tidak dapat disimpulkan dari penggunaan. Coba tentukan argumen tipe secara eksplisit.

Apa yang salah dengan pendekatan saya?


person lolcat    schedule 22.02.2009    source sumber


Jawaban (1)


Salah satu masalah yang saya lihat adalah dalam cuplikan kode terakhir, ...Elements("userid") mengembalikan daftar objek XElement yang tidak dapat berisi String yang dikembalikan oleh properti Value. Ini seharusnya berhasil...

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

Namun saya akan melakukan ini dengan menggunakan kueri gabung.. Pilih daftar nama pengguna yang bergabung di userid
Akan jadi seperti ini

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

Keluaran:

User on roster       on Roster R1
person Gishu    schedule 22.02.2009