Select nodes Linq to Xml C#
31,092
Solution 1
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);
}
}
Solution 2
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"));
Solution 3
Try this:
var query = for x in xDoc.Descendants("url")
select (string)x.Element("loc");
foreach (string loc in query)
{
urlList.Add(loc);
}
Comments
-
Chelsea_cole over 3 years
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); }
-
Jon Skeet over 12 yearsThat will return an
IEnumerable<IEnumerable<XElement>>
which I don't think is what was wanted... -
Chelsea_cole over 12 yearsHi Jon! I used your code but my urlList still empty! :( (i parse xml from a string).
-
Jon Skeet over 12 years@Chelsea_cole: Works for me - I've posted a complete program showing it working. Note that I had to fix up your original XML, from
<urlset>
at the end to</urlset>
. Please try my code, and then see what the difference is between that and what you were trying... -
Chelsea_cole over 12 yearsYour code really work! But still not for me :( Maybe it's because my streamreader string?) StreamReader streamReader = new StreamReader(@"D:\data.xml"); string text = streamReader.ReadToEnd(); streamReader.Close(); XDocument doc = XDocument.Parse(text);
-
Jon Skeet over 12 yearsIt's more likely to be because your XML isn't the same as what you've posted. But it's not a great idea to parse XML like that anyway: it's assuming UTF-8, whereas
XDocument
can do the right thing for multiple encodings; you should use ausing
statement instead of closing explicitly; to read the whole of a file you can useFile.ReadAllText
; you can do all of this in one call anyway withXDocument.Load(string)
. -
Jon Skeet over 12 yearsThe way that
Descendants()
works, there's no need to useSelectMany
- there's an overload which starts with anIEnumerable<XElement>
. -
Jon Skeet over 12 years@CJohnson: I suggest you ask a new question with a short but complete example of what you're trying to do then. It's impossible to tell what's wrong just from your comment.