Return all xml elements with the same name in linq

how can I request an xml file where I have several elements with the same name so that I can return all the elements. Currently, I get only the first result. I managed to get it to work with the following code, but this returns all the elements where specific search criteria are met. What I want as a conclusion is to get two results back where, for example, Dublin is located. The question is how can I achieve this using linq for xml

Greetings from Chris

Here is the code

string location = "Oslo"; var training = (from item in doc.Descendants("item") where item.Value.Contains(location) select new { event = item.Element("event").Value, event_location = item.Element("location").Value }).ToList(); 

The xml file is as follows:

 <training> <item> <event>C# Training</event> <location>Prague</location> <location>Oslo</location> <location>Amsterdam</location> <location>Athens</location> <location>Dublin</location> <location>Helsinki</location> </item> <item> <event>LINQ Training</event> <location>Bucharest</location> <location>Oslo</location> <location>Amsterdam</location> <location>Helsinki</location> <location>Brussels</location> <location>Dublin</location> </item> </training> 
+4
source share
2 answers

You are using item.Element("location") , which returns the first location item below the item. This is not necessarily the place you were looking for!

I suspect you really want something more:

 string location = "Oslo"; var training = from loc in doc.Descendants("location") where loc.Value == location select new { event = loc.Parent.Element("event").Value, event_location = loc.Value }; 

But then again, what is the meaning of event_location , given that it will always be the location that you passed in the request?

If this is not what you want, please give more detailed information - your question is a little difficult to understand at the moment. The details of what your current code is giving and what you want to give would be useful, as well as what you mean by "name" (in the sense that you really mean "value").

EDIT: Alright, it looks like you want:

 string location = "Oslo"; var training = from loc in doc.Descendants("location") where loc.Value == location select new { event = loc.Parent.Element("event").Value, event_locations = loc.Parent.Elements("location") .Select(e => e.Value) }; 

event_locations will now be a sequence of strings. You can get the desired result:

 for (var entry in training) { Console.WriteLine("Event: {0}; Locations: {1}", entry.event, string.Join(", ", entry.event_locations.ToArray()); } 

Give it a try and see if you want ...

+4
source

This may not be the most efficient way to do this, but this query works:

 var training = (from item in root.Descendants("item") where item.Value.Contains(location) select new { name = item.Element("event").Value, location = (from node in item.Descendants("location") where node.Value.Equals(location) select node.Value).FirstOrDefault(), }).ToList(); 

(Note that the code will not compile if the property name was event , so I changed it to name .)

I believe the problem with your code was that the location node retrieved when creating the anonymous type was not looking for the node with the desired value.

0
source

All Articles