C # Linq XML Query where multiple elements with the same name exist
Linq newbie here. There was a search and could not find the exact question; tried to work from other answers that were similar but still couldn't get it.
Cannot return all instances of the specified item name. I can return one item, but not all.
Here is the XML:
<?xml version="1.0"?>
<printerlist>
<list type="aff">
<printserver>print-server1</printserver>
<printserver>print-server2</printserver>
<printserver>print-server3</printserver>
</list>
<list type="lff">
<printserver>print-sever4</printserver>
<additionalprinters>
<printer>
<fullname>\\serverb\bbb</fullname>
</printer>
<printer>
<fullname>\\serverc\aaa</fullname>
</printer>
</additionalprinters>
</list>
</printerlist>
And here is the code to try and get the list:
var query = from c in xml.Root.Descendants("list")
where (string)c.Attribute("type") == "aff"
select c.Element("printserver");
foreach (string name in query)
{
Console.WriteLine("Server Name: {0}", name);
}
This only creates the first printserver server element: print-server1 How can I get foreach to list all 3 servers that are in the contact list?
thank
source to share
You need to use Elements("printserver")
instead Element("printserver")
like this:
var query = (from c in doc.Root.Descendants("list").Elements("printserver")
where (string)c.Parent.Attribute("type") == "aff"
select c);
or using SelectMany()
like this:
var query = (from c in doc.Root.Descendants("list")
where (string)c.Attribute("type") == "aff"
select c).SelectMany(c => c.Elements("printserver"));
or if you are sure that only one item matches the sentence where
, you can use First()
like this:
var query = (from c in doc.Root.Descendants("list")
where (string)c.Attribute("type") == "aff"
select c).First().Elements("printserver"));
source to share
How about something like this:
List<XElement> elements = doc.Root.Descendants("printserver")
.Where(e => e.Parent.Name == "list" && e.Parent.Attribute("type").Value == "aff")
.ToList();
Then if you want to loop through the elements:
foreach (XElement e in elements)
{
Console.WriteLine("Server Name : {0}", e.Value);
}
If you just want string values ββfor each print server, use .Select at the end:
List<string> elements = doc.Root.Descendants("printserver")
.Where(e => e.Parent.Name == "list" && e.Parent.Attribute("type").Value == "aff")
.Select(p => p.Value)
.ToList();
The above solution allows you to use your current foreach loop.
source to share