C# Linq to Xml: több eredmény egy property-be illesztése

C# Linq to Xml: több eredmény egy property-be illesztése
2015-10-12T14:16:49+02:00
2015-10-13T13:44:19+02:00
2022-12-02T21:35:35+01:00
BIG W
Üdv!

Nagyon egyszerű problémám lenne, ami a következő:

Van egy fő xml "táblám", amihez hozzácsatolok 2 másik táblát join-nal. Na már most a join-nal az eredményem a fő xml táblában egy többször ismétlődő rekord. Ezt Distinct-tes (.GroupBy(i=>i.ID).Select(grp=>grp.First())) megoldással kiszűrtem.

IEnumerable<Training> trainingsIE = (from trainingsDoc in trainingsXDocument.Element("trainings").Descendants("training") join trainingsMuscleGroupsDoc in trainingsMuscleGroupsXDocument.Element("trainingsmusclegroups").Descendants("trainingmusclegroup") on trainingsDoc.Element("id").Value equals trainingsMuscleGroupsDoc.Element("trainingid").Value join muscleGroupsDoc in muscleGroupsXDocument.Element("musclegroups").Descendants("musclegroup") on trainingsMuscleGroupsDoc.Element("musclegroupid").Value equals muscleGroupsDoc.Element("id").Value where trainingsDoc.Element("trainingplanid").Value == TrainingPlanGuid.ToString() select new Training { ID = Guid.Parse(trainingsDoc.Element("id").Value), Title = trainingsDoc.Element("title").Value, Description = trainingsDoc.Element("description").Value, Day = new Days { ID = Convert.ToInt32(trainingsDoc.Element("day").Value), Day = (from day in DaysList where day.ID == Convert.ToInt32(trainingsDoc.Element("day").Value) select day.Day).SingleOrDefault() }, //ide kellene jönnie a MuscleGroups=muscleGroupsDoc.Element("name").Value-nak, vesszővel elválasztva }).GroupBy(i=>i.ID).Select(grp=>grp.First()).ToList();
Most azt szeretném, hogy a muscleGroupsDoc-ból kiszedjem a name elementet, és egy vesszővel elválasztva átadjam a Training.MuscleGroups tulajdonságnak. Hogyan tudnám ezt megoldani?
Mutasd a teljes hozzászólást!
Meg is van:

IEnumerable<Training> trainingsIE = (from trainingsDoc in trainingsXDocument.Element("trainings").Descendants("training") where trainingsDoc.Element("trainingplanid").Value == TrainingPlanGuid.ToString() select new Training { ID = Guid.Parse(trainingsDoc.Element("id").Value), Title = trainingsDoc.Element("title").Value, Description = trainingsDoc.Element("description").Value, Day = new Days { ID = Convert.ToInt32(trainingsDoc.Element("day").Value), Day = (from day in DaysList where day.ID == Convert.ToInt32(trainingsDoc.Element("day").Value) select day.Day).SingleOrDefault() }, MuscleGroups = string.Join(",", (from musclegroups in muscleGroupsXDocument.Element("musclegroups").Descendants("musclegroup") join trainingsMuscleGroupsDoc in trainingsMuscleGroupsXDocument.Element("trainingsmusclegroups").Descendants("trainingmusclegroup") on trainingsDoc.Element("id").Value equals trainingsMuscleGroupsDoc.Element("trainingid").Value where trainingsMuscleGroupsDoc.Element("musclegroupid").Value==musclegroups.Element("id").Value select musclegroups.Element("name").Value).ToArray()) }).ToList();
Ez már egy működőképes kód.:)
Mutasd a teljes hozzászólást!

  • Ha jól értem, és sima szövegként szeretnéd: csinálhatnál hozzá egy select-et, hogy legyen egy listád csak a nevekből, majd toArray, és string.join.

    Ezt nézegettem: Concat all strings inside a List<string> using LINQ - az elfogadott megoldás elég egzotikus, úgyhogy az alatta levőt
    Mutasd a teljes hozzászólást!
  • Szia!

    Igen, szövegként, vesszővel elválasztva, igazából amire utaltál, azt már kipróbáltam, de nagyon sokféle variációban. Most már itt megálltam:

    MuscleGroups=string.Join(",",Convert.ToString(muscleGroupsDoc.Elements("name").ToArray()))
    Ez eredményül "System.Xml.Linq.XElement[]"-et ad, és fogalmam sincs miért.

    Talán az még segít, ha bemásolom az Xml-ek struktúráját:
    Ez a Trainings.xml, amit a fenti kódban a trainingsXDocument nevű XDocument változó kapja betöltéskor:

    <?xml version="1.0" encoding="utf-8"?> <trainings> <training> <id>f4156cb0-183b-4358-8501-7df0f7ef9902</id> <title>2x20 combhajlító</title> <day>1</day> <description></description> <trainingplanid>468ad0df-3cc1-424c-b88b-10fa955b61c4</trainingplanid> </training> </trainings>
    Ez a MuscleGroups.xml, amit a fenti kódban a muscleGroupsXDocument nevű XDocument változó kapja betöltéskor:

    <?xml version="1.0" encoding="utf-8" ?> <musclegroups> <musclegroup> <id>1</id> <name>Belső combizom</name> </musclegroup> <musclegroup> <id>2</id> <name>Bicepsz</name> </musclegroup> <musclegroup> <id>3</id> <name>Combhajlító</name> </musclegroup> <musclegroup> <id>4</id> <name>Csuklyás izom (trapéz izom) felső része</name> </musclegroup> <musclegroup> <id>5</id> <name>Egyenes hasizom felső része</name> </musclegroup> <musclegroup> <id>6</id> <name>Egyenes hasizom alsó része</name> </musclegroup> <musclegroup> <id>7</id> <name>Elülső deltaizom</name> </musclegroup> <musclegroup> <id>8</id> <name>Ferde hasizom</name> </musclegroup> <musclegroup> <id>9</id> <name>Gerincmerevítő hátizom</name> </musclegroup> <musclegroup> <id>10</id> <name>Hátsó delta izom</name> </musclegroup> <musclegroup> <id>11</id> <name>Mellizom</name> </musclegroup> <musclegroup> <id>12</id> <name>Mellizom felső része</name> </musclegroup> <musclegroup> <id>13</id> <name>Nagy farizom</name> </musclegroup> <musclegroup> <id>14</id> <name>Négyfejű combizom</name> </musclegroup> <musclegroup> <id>15</id> <name>Széles hátizom</name> </musclegroup> <musclegroup> <id>16</id> <name>Trapéz izom alsó része</name> </musclegroup> <musclegroup> <id>17</id> <name>Tricepsz</name> </musclegroup> <musclegroup> <id>18</id> <name>Vádli</name> </musclegroup> </musclegroups>
    És jön a TrainingsMuscleGroups.xml, amit a fenti kódban a trainingsMuscleGroupsXDocument nevű XDocument változó kap betöltéskor. Ennek a lényege, hogy egy training-nek lehet több musclegroup-ja, és a musclegroup name-jét kell abba a változóba betölteni veszővel elválasztva:

    <?xml version="1.0" encoding="utf-8"?> <trainingsmusclegroups> <trainingmusclegroup> <trainingid>f4156cb0-183b-4358-8501-7df0f7ef9902</trainingid> <musclegroupid>1</musclegroupid> </trainingmusclegroup> <trainingmusclegroup> <trainingid>f4156cb0-183b-4358-8501-7df0f7ef9902</trainingid> <musclegroupid>3</musclegroupid> </trainingmusclegroup> </trainingsmusclegroups>
    Megjegyzés: Az xml-t nem az adatok miatt másoltam be, hanem hogy segítsek abban, hogy néz ki strukturált szempontból az xml felépítése. Remélem, így érthető lesz. Sajnos a string.join()-nal sokat szenvedtem, de nem tudtam kiszedni az 1-es, és a 3-as id-val rendelkező musclegroup name-jét, ha mégis, akkor is csak 1-et.
    Mutasd a teljes hozzászólást!
  • A Convert.ToString(muscleGroupsDoc.Elements("name").ToArray()) így önmagában eredményezi a System.Xml.Linq.XElement[]-t. Ez így kvázi egy ToString hívás a tömbre.

    Mivel a tömbből nem lehet szöveget csinálni, azért kéne a select, valami olyasmi, hogy

    string.Join(",",muscleGroupsDoc.Select(grp => grp.Element("name").Value).ToArray())

    sajnos csak ugatom a témát és ma már biztosan nem lesz időm kipróbálni.
    Mutasd a teljes hozzászólást!
  • IEnumerable<Training> trainingsIE = (from trainingsDoc in trainingsXDocument.Element("trainings").Descendants("training") join trainingsMuscleGroupsDoc in trainingsMuscleGroupsXDocument.Element("trainingsmusclegroups").Descendants("trainingmusclegroup") on trainingsDoc.Element("id").Value equals trainingsMuscleGroupsDoc.Element("trainingid").Value join muscleGroupsDoc in muscleGroupsXDocument.Element("musclegroups").Descendants("musclegroup") on trainingsMuscleGroupsDoc.Element("musclegroupid").Value equals muscleGroupsDoc.Element("id").Value where trainingsDoc.Element("trainingplanid").Value == TrainingPlanGuid.ToString() select new Training { ID = Guid.Parse(trainingsDoc.Element("id").Value), Title = trainingsDoc.Element("title").Value, Description = trainingsDoc.Element("description").Value, Day = new Days { ID = Convert.ToInt32(trainingsDoc.Element("day").Value), Day = (from day in DaysList where day.ID == Convert.ToInt32(trainingsDoc.Element("day").Value) select day.Day).SingleOrDefault() }, MuscleGroups = string.Join(", ", muscleGroupsDoc.Elements("name").Select(i=>i.Value).ToList()) }).GroupBy(i => i.ID).Select(grp => grp.First()).ToList();
    Így megjeleníti a MuscleGroup értékét, de csak egyet a 2-ből. Tesztelés során rájöttem, hogy azért nem Join-olja hozzá a másodikat, mert még így is 2 Training objektumot hoz létre, az egyikbe az első muscelgroup-ot rakja, a másikba a másik musclegroup-ot, és a .GroupBy(i=>i.ID).Select(grp=>grp.First()) miatt ugye csak egy Training-et ad vissza az ismétlődőkből.
    Szerk.:
    Úgy írom át, hogy ne a training ismétlődjön, hanem a muscleGroup-on belül hajtok végre egy belső lekérdezést.
    Mutasd a teljes hozzászólást!
  • Meg is van:

    IEnumerable<Training> trainingsIE = (from trainingsDoc in trainingsXDocument.Element("trainings").Descendants("training") where trainingsDoc.Element("trainingplanid").Value == TrainingPlanGuid.ToString() select new Training { ID = Guid.Parse(trainingsDoc.Element("id").Value), Title = trainingsDoc.Element("title").Value, Description = trainingsDoc.Element("description").Value, Day = new Days { ID = Convert.ToInt32(trainingsDoc.Element("day").Value), Day = (from day in DaysList where day.ID == Convert.ToInt32(trainingsDoc.Element("day").Value) select day.Day).SingleOrDefault() }, MuscleGroups = string.Join(",", (from musclegroups in muscleGroupsXDocument.Element("musclegroups").Descendants("musclegroup") join trainingsMuscleGroupsDoc in trainingsMuscleGroupsXDocument.Element("trainingsmusclegroups").Descendants("trainingmusclegroup") on trainingsDoc.Element("id").Value equals trainingsMuscleGroupsDoc.Element("trainingid").Value where trainingsMuscleGroupsDoc.Element("musclegroupid").Value==musclegroups.Element("id").Value select musclegroups.Element("name").Value).ToArray()) }).ToList();
    Ez már egy működőképes kód.:)
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd