linq to xml get all child nodes

18,544

I think you want this:

    IEnumerable<XElement> xmlURL =
        from el in xmlFile.Root.Descendants("service")
        where (string)el.Attribute("name") == serviceString
        select el.Descendants("endpoint");

    Console.WriteLine("Start: " + serviceString);
    foreach (XElement el in xmlURL)
    {
        Console.WriteLine(el);
    }
    Console.WriteLine("End: " + serviceString + "\n\n");

Notice I'm selecting el.Descendants() rather than Element() which will only ever return the first match (http://msdn.microsoft.com/en-us/library/system.xml.linq.xcontainer.element.aspx).

** UPDATE **

I think this is what you want, because you're only conerned with one specific match.

IEnumerable<XElement> xmlURL = 
    (from el in doc.Root.Descendants("service")
    where el.Attribute("name").Value == serviceString
    select el).First().Descendants();

So the result of the LINQ query is, as the compiler tells you, an IEnumerable of IEnumerables, so I take the First() result of which gives me now an IEnumerable<XElement>, and then we call Descendants() on that, which gives you an IEnumerable of the endpoint XElement's.

Also note here that I used the Value property of the XAttribute, you can't simply cast the XAttribute to a string, you have to use that Value property. I didn't catch that in my initial copy/paste answer.

** UPDATE 2 **

The above query can is probably a little easier to understand like this:

doc.Root.Descendants("service")
   .Where(x => x.Attribute("name").Value == serviceString)
   .First()
   .Descendants();

** UPDATE 3 **

There is also the potential for a NRE on the attribute matching, so again this is probably an even better verison. =)

doc.Root.Descendants("service")
   .Where(x => x.Attribute("name") != null && x.Attribute("name").Value == serviceString)
   .First()
   .Descendants();
Share:
18,544
webdad3
Author by

webdad3

Been programming for a while, and I can honestly say I've embraced my inner nerdiness. By doing so that has helped my programming skills as I work on a side project almost every night after coding for my job. I really think mobile application development is where the future of the industry is going. Most of my side projects are now related to the Windows Phone 8 and Windows 8. However, I do all my web work using PHP and MVC. I try to follow the mantra of keep it simple stupid! I'm focusing on networking and becoming part of the community of developers. Not only to help myself, but also to help others. Wisdom is earned through many failures (big and small). You can also follow me on Twitter!

Updated on July 17, 2022

Comments

  • webdad3
    webdad3 almost 2 years

    I'm trying to query a web.Config file that contains WCF entries.

    In the <service> node there is a name attribute that I am trying to match off of. So far my code has worked when doing the matching, but my issue is that it only returns 1 of the <endpoint> nodes.

    For example I could have this snippet of xml:

    <service name="a">
    <endpoint>1</endpoint>
    <endpoint>2</endpoint>
    <endpoint>3</endpoint>
    </service>
    <service name="b">
    <endpoint>1</endpoint>
    <endpoint>2</endpoint>
    </service>
    

    Everytime I get a match I want it to display all the <endpoint> child nodes for that match.

    This is the code I have so far:

            IEnumerable<XElement> xmlURL =
                from el in xmlFile.Root.Descendants("service")
                where (string)el.Attribute("name") == serviceString
                select el.Element("endpoint");
    
            Console.WriteLine("Start: " + serviceString);
            foreach (XElement el in xmlURL)
            {
                Console.WriteLine(el);
            }
            Console.WriteLine("End: " + serviceString + "\n\n");
    

    Currently when it does the match only 1 endpoint is shown.