Chelsea_cole
Chelsea_cole

Reputation: 1095

Select nodes Linq to Xml C#

XML file format:

<?xml version="1.0" encoding="UTF-8"?>
    <urlset>    
        <url>
            <loc>element1</loc>
            <changefreq>daily</changefreq>
            <priority>0.2</priority>
        </url>
        <url>
            <loc>element2</loc>
            <changefreq>daily</changefreq>
            <priority>0.2</priority>
        </url>
    <urlset>

I want to select all "loc" nodes (element1, element2), but this not work!!!

 foreach (XElement item in document.Elements("url").Descendants("loc")) // Change into what?
 {
      urlList.Add(item.Value);
 }

Upvotes: 6

Views: 33487

Answers (3)

VMAtm
VMAtm

Reputation: 28355

var xDoc = XDocument.Parse(
    @"<urlset>    
        <url>
            <loc>element1</loc>
            <changefreq>daily</changefreq>
            <priority>0.2</priority>
        </url>
        <url>
            <loc>element2</loc>
            <changefreq>daily</changefreq>
            <priority>0.2</priority>
        </url>
    </urlset>");
var locElements = xDoc.Descendants("url").SelectMany(el => el.Descendants("loc"));

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1499770

I suspect the problem is that you're going from document.Elements("url") instead of document.Root.Elements("url")... so it's looking for a root element of url, which doesn't exist.

Try this:

List<string> urlList = doc.Root.Elements("url")
                               .Elements("loc")
                               .Select(x => (string) x)
                               .ToList();

Note that I haven't used Descendants here, as the loc elements are all directly beneath url elements anyway.

Another alternative you could use if the only loc elements are the right ones anyway, is just:

List<string> urlList = doc.Descendants("loc")
                          .Select(x => (string) x)
                          .ToList();

(I'm assuming urlList was empty beforehand... for this sort of situation I like to use LINQ for the whole operation and eliminate foreach loops that are just adding to a collection.)

EDIT: The code works for me. Here's a short but complete program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

class Test
{
    static void Main(string[] args)
    {
        string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
    <urlset>    
        <url>
            <loc>element1</loc>
            <changefreq>daily</changefreq>
            <priority>0.2</priority>
        </url>
        <url>
            <loc>element2</loc>
            <changefreq>daily</changefreq>
            <priority>0.2</priority>
        </url>
    </urlset>";

        XDocument doc = XDocument.Parse(xml);
        List<string> urlList = doc.Root
                                  .Elements("url")
                                  .Elements("loc")
                                  .Select(x => (string) x)
                                  .ToList();
        Console.WriteLine(urlList.Count);
    }
}

Upvotes: 12

Tim
Tim

Reputation: 28520

Try this:

var query = for x in xDoc.Descendants("url")
            select (string)x.Element("loc");

foreach (string loc in query)
{
    urlList.Add(loc);
}

Upvotes: 1

Related Questions