3

Linq newbie here. Did the searching, and couldn't find an exact question; tried to work from other answers that were similar, but still couldn't get it.

Having trouble returning all instances of a particular element name. I can get one item returned, just not them 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 produces the first element of printserver: print-server1 How can I get the foreach to list all 3 servers that are in the aff list?

Thanks

2
  • Perhaps because you are using c.Element instead of c.Elements? I don't have access to a compiler to test this just now. Commented Aug 15, 2014 at 12:07
  • Hi, both comments above do not work when superimposed directly onto the existing code. They may work with a little more massaging.... but thanks for the input, has been answered below. Commented Aug 15, 2014 at 12:33

2 Answers 2

2

You need to use Elements("printserver") instead of Element("printserver") like so :

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 only one element match the where clause, 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"));
Sign up to request clarification or add additional context in comments.

2 Comments

Hi thanks, this works and is not too far off my original code using traditional query. It's interesting to see the different ways that this can be achieved. One way may prove better than another when I expand on my queries at a later date.
Updated my answer with another possible way. Glad to know this answer helped.
1

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 the string-values of each printserver, use a .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();

Above solution allows the use of your current foreach-loop.

2 Comments

Hi. This works perfectly too... but I can only choose one answer. In my case, I was trying to use LINQ with the traditional query notation (rather than Lambda, which is the answer you provided if I understand correctly)... and as I am still getting used to LINQ I thought I would mark the tradition as my answer. But thank you - I will be looking at the differences between the two.
@MrBeatnik: Sure, no problem! LINQ and Lambda are often used togheter. If you're interested in learning more about the two, read here: codeproject.com/Articles/33769/Basics-of-LINQ-Lamda-Expressions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.