2

I've got this file:

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://purl.org/atom/app#' xmlns:media='http://search.yahoo.com/mrss/' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:gml='http://www.opengis.net/gml' xmlns:yt='http://gdata.youtube.com/schemas/2007' xmlns:georss='http://www.georss.org/georss'>
    <id>http://gdata.youtube.com/feeds/api/users/snifyy/favorites</id>
    <updated>2011-09-26T16:21:40.933Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#video'/>
    <title type='text'>Favorites of snifyy</title>
    <logo>http://www.youtube.com/img/pic_youtubelogo_123x63.gif</logo>
    <author>
        <name>snifyy</name>
        <uri>http://gdata.youtube.com/feeds/api/users/snifyy</uri>
    </author>
    <generator version='2.1' uri='http://gdata.youtube.com'>YouTube data API</generator>
    <openSearch:totalResults>631</openSearch:totalResults>
    <openSearch:startIndex>1</openSearch:startIndex>
    <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
    <entry>
        <id>http://gdata.youtube.com/feeds/api/videos/LXO-jKksQkM</id>
        <published>2011-09-23T16:15:27.000Z</published>
        <updated>2011-09-26T16:21:15.000Z</updated>
        <title type='text'>PUMPED UP KICKS|DUBSTEP</title>
        <content type='text'>DUBSTEPPIN!!! to a beast track remixed by "butch clancy"</content>
        <link rel='alternate' type='text/html' href='http://www.youtube.com/watch?v=LXO-jKksQkM&amp;feature=youtube_gdata'/>
        <link rel='http://gdata.youtube.com/schemas/2007#video.responses' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/LXO-jKksQkM/responses'/>
        <link rel='http://gdata.youtube.com/schemas/2007#video.related' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/LXO-jKksQkM/related'/>
        <link rel='http://gdata.youtube.com/schemas/2007#mobile' type='text/html' href='http://m.youtube.com/details?v=LXO-jKksQkM'/>
        <link rel='related' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/LXO-jKksQkM'/>
        <link rel='self' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/users/snifyy/favorites/LXO-jKksQkM'/>
        <author>
            <name>WHZGUD2</name>
            <uri>http://gdata.youtube.com/feeds/api/users/whzgud2</uri>
        </author>
        <gd:comments>
            <gd:feedLink href='http://gdata.youtube.com/feeds/api/videos/LXO-jKksQkM/comments' countHint='3738'/>
        </gd:comments>
        <media:group>
            <media:category label='Entertainment' scheme='http://gdata.youtube.com/schemas/2007/categories.cat'>Entertainment</media:category>
            <media:content url='http://www.youtube.com/v/LXO-jKksQkM?f=user_favorites&amp;app=youtube_gdata' type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='327' yt:format='5'/>
            <media:content url='rtsp://v3.cache5.c.youtube.com/CioLENy73wIaIQlDQiypjL5zLRMYDSANFEgGUg51c2VyX2Zhdm9yaXRlcww=/0/0/0/video.3gp' type='video/3gpp' medium='video' expression='full' duration='327' yt:format='1'/>
            <media:content url='rtsp://v1.cache2.c.youtube.com/CioLENy73wIaIQlDQiypjL5zLRMYESARFEgGUg51c2VyX2Zhdm9yaXRlcww=/0/0/0/video.3gp' type='video/3gpp' medium='video' expression='full' duration='327' yt:format='6'/>
            <media:description type='plain'>DUBSTEPPIN!!! to a beast track remixed by "butch clancy"</media:description>
            <media:keywords>DUBSTEP, butch, clancy, bass</media:keywords>
            <media:player url='http://www.youtube.com/watch?v=LXO-jKksQkM&amp;feature=youtube_gdata_player'/>
            <media:thumbnail url='http://i.ytimg.com/vi/LXO-jKksQkM/0.jpg' height='360' width='480' time='00:02:43.500'/>
            <media:thumbnail url='http://i.ytimg.com/vi/LXO-jKksQkM/1.jpg' height='90' width='120' time='00:01:21.750'/>
            <media:thumbnail url='http://i.ytimg.com/vi/LXO-jKksQkM/2.jpg' height='90' width='120' time='00:02:43.500'/>
            <media:thumbnail url='http://i.ytimg.com/vi/LXO-jKksQkM/3.jpg' height='90' width='120' time='00:04:05.250'/>
            <media:title type='plain'>PUMPED UP KICKS|DUBSTEP</media:title>
            <yt:duration seconds='327'/>
        </media:group>
        <gd:rating average='4.96415' max='5' min='1' numRaters='24435' rel='http://schemas.google.com/g/2005#overall'/>
        <yt:statistics favoriteCount='16660' viewCount='924793'/>
    </entry>
</feed>

And I want to load all entries and then their title, content and thumbnail. But I have problems even loading the entries. That's my code (data is this xml):

    XmlDocument xml = new XmlDocument();
    xml.LoadXml(data);

    XmlNodeList xnList = xml.SelectNodes("feed/entry");
    foreach (XmlNode xn in xnList) {
        Debug.WriteLine(xn.LocalName.ToString());
    }
blez
  • 4,939
  • 5
  • 50
  • 82

4 Answers4

3

The problem is that your XPath doesn't specify the namespaces (so you're actually searching for names with null namespace URIs). Given that feed is the top level element, it's a pretty trivial query - I don't think using XPath is actually helping you here. Try this instead, using XmlElement.GetElementsByTagName:

XmlElement root = doc.DocumentElement;
String atomUri = "http://www.w3.org/2005/Atom";
foreach (XmlElement element in root.GetElementsByTagName("entry", atomUri))
{
    // Use element here
}

(If you get the chance to use .NET 3.5, I suggest you start using LINQ to XML - it's much nicer :)

EDIT: Here's a short but complete program printing out the url attribute of each content element:

using System;
using System.Xml;

class Program
{
    static void Main(string[] args)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load("test.xml");

        XmlElement root = doc.DocumentElement;
        String atomUri = "http://www.w3.org/2005/Atom";
        String mediaUri = "http://search.yahoo.com/mrss/";
        foreach (XmlElement entry in root.GetElementsByTagName("entry", atomUri))
        {
            foreach (XmlElement group in 
                     entry.GetElementsByTagName("group", mediaUri))
            {
                foreach (XmlElement content in 
                         entry.GetElementsByTagName("content", mediaUri))
                {
                    Console.WriteLine(content.Attributes["url"].Value);
                }
            }
        }
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Note that the OP wants the "entry" elements. – LarsH Sep 26 '11 at 17:03
  • Strongly agree on using LINQ to XML for this. It's a lot easier than XPath. – James Johnson Sep 26 '11 at 17:04
  • OP specified the tag C#-2.0, so probably it's technical restrictions of using .net 2.0 – Samich Sep 26 '11 at 17:06
  • @blez: Try the code I've given now. It should work fine. I've just tried it myself. (I had a typo before.) – Jon Skeet Sep 26 '11 at 17:06
  • @Samich: Yes, that's why I said *If you get the chance to use .NET 3.5*, but still gave an answer using .NET 2.0. – Jon Skeet Sep 26 '11 at 17:06
  • @JonSkeet: miss it, yep, sorry – Samich Sep 26 '11 at 17:07
  • @blez: The code I've given *does* work with the XML you specified. Either the XML isn't as you showed it, or you haven't used my modified code. It really is a lot simpler not to use xpath here. – Jon Skeet Sep 26 '11 at 17:17
  • My bad. It works indeed. But how to read the name of the node? I tried with element.LocalName and Name – blez Sep 26 '11 at 17:25
  • @blez: Both of those should work fine. What problems have you had? I've edited my answer to show an example which reads all the `media:content` elements and prints out the `url` attribute. – Jon Skeet Sep 26 '11 at 17:36
  • 1
    @blez, when you say "I tried X and Y", don't forget to say what the result was. We can't read minds. – LarsH Sep 26 '11 at 20:37
  • "The problem is that your XPath *doesn't specify the namespaces*" - I think it would be accurate to say that the original XPath expression given **specifies a null namespace URI** (by lack of a namespace prefix). Assuming XPath 1.0: "if the QName does not have a prefix, then the namespace URI is null" (http://www.w3.org/TR/xpath/#node-tests) – LarsH Sep 26 '11 at 20:44
  • @LarsH: Yes, that's more accurate - but I suspect actually gets in the way a bit. I'll edit a bit though :) – Jon Skeet Sep 26 '11 at 20:51
  • Agreed, accuracy does not always communicate best. But in this case I think what trips so many people up is that omitting a namespace does not mean "regardless of namespace" as they might expect, (nor, unlike in XML, does it mean "in the default namespace at that point in the document",) but rather "in the null namespace." – LarsH Sep 26 '11 at 20:53
  • @LarsH: Right. Yes, it's a pain in that respect... One of the reasons I prefer using code rather than XPath for searching :) – Jon Skeet Sep 26 '11 at 21:00
2

You can use XmlNamespaceManager to specify namspace from your feed:

XmlDocument xDoc = new XmlDocument();
xDoc.Load(data);

XmlNamespaceManager manager = new XmlNamespaceManager(xDoc.NameTable);
manager.AddNamespace("atom", "http://www.w3.org/2005/Atom");

XmlNodeList xnList = xDoc.SelectNodes("atom:feed/atom:entry", manager);
foreach (XmlNode xn in xnList)
{
    Debug.WriteLine(xn.LocalName.ToString());
}

And any type when you trying to select nodes use prefix of the namespace, eg: atom:feed/atom:entry

Adding another namespace to work with multiple ones:

XmlNamespaceManager manager = new XmlNamespaceManager(xDoc.NameTable);
manager.AddNamespace("atom", "http://www.w3.org/2005/Atom");
manager.AddNamespace("media", "http://search.yahoo.com/mrss/");

XmlNodeList mediaNodes = xDoc.SelectNodes("atom:feed/atom:entry/media:group", manager);
Samich
  • 29,157
  • 6
  • 68
  • 77
  • You need to add namespace to the manager and use appropriate prefix. Just a sec, I'll add it. – Samich Sep 26 '11 at 17:26
0

You need to use the Atom namespace when you select the feed/entry elements.

Create a namespace manager, add a namespace prefix for the Atom namespace, and then use it in your XPath expression.

For example code, see the accepted answer to this question.

Community
  • 1
  • 1
LarsH
  • 27,481
  • 8
  • 94
  • 152