XPath & Namespaces

I'm sure many out there know this or figured it out eons ago, but it was new to me and took awhile to figure out.

Say you have a RDF style XML document that looks something like:

<?xml version="1.0" encoding="iso-8859-1" ?>
<
rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns
="http://purl.org/rss/1.0/">
<
channel rdf:about
="http://someplace.com/weblog/">
<
title>
News from Bob</title>
<
link>http:// someplace.com/weblog/</link
>
<
description></description
>
<
dc:language>en-us</dc:language
>
<
dc:creator>Bob</dc:creator
>
<
dc:rights>Copyright 2003 Bob</dc:rights
>
<
dc:date>2003-03-19T22:30:34-07:00</dc:date
>
<
admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=2.51"
/>
<
admin:errorReportsTo rdf:resource="mailto:tbob@somewhere.com"
/>
<
sy:updatePeriod>hourly</sy:updatePeriod
>
<
sy:updateFrequency>1</sy:updateFrequency
>
</
channel
>
<
item rdf:about
="http://somewhere/weblog/archives/2003/03/19.shtml#how_i_really_feel_about_cheese">
<
title>How I really feel about Cheese</title
>
<
description>&lt;p
&gt;
I was asked in a comment why I really don't like cheese...</description>
</item>
</rdf:RDF>

Simplistically I thought the following code would work:

XmlNode dateNode = rdfXml.SelectSingleNode("/RDF/channel/date");

But of course it returns Null. So I tried the following:

XmlNode dateNode = rdfXml.SelectSingleNode("/rdf:RDF/channel/dc:date");

 

Of course this returned Null as well. So it was time to turn to the help file, which didn’t help much. My next best friend is Google, and Google Groups didn’t let me down. Turns out SelectSingleNode is overloaded and takes a XmlNamespaceManager as the second parameter. I now had this:

 

nsMgr = new XmlNamespaceManager(rdfXml.NameTable);

nsMgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");

nsMgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");

 

XmlNode dateNode = rdfXml.SelectSingleNode("/rdf:RDF/channel/dc:date", nsMgr);

 

However, I didn’t know what to do with the default namespace. A little more research lead me to the nugget that there is no such thing as a default namespace in XPath, so all I has to do was add the default namespace with the prefix of my choosing.

 

nsMgr = new XmlNamespaceManager(feedXml.NameTable);

nsMgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");

nsMgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");

nsMgr.AddNamespace("rss", "http://purl.org/rss/1.0/");

 

XmlNode dateNode = rdfXml.SelectSingleNode("/rdf:RDF/rss:channel/dc:date", nsMgr);

 

Now everything works like it should.

 

Full example (.Net 2.0):

 

using System.Xml;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument rdfXml = new XmlDocument();
            rdfXml.Load("data.xml");
            XmlNamespaceManager nsMgr = new XmlNamespaceManager(rdfXml.NameTable);
            nsMgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
            nsMgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
            nsMgr.AddNamespace("rss", "http://purl.org/rss/1.0/");

            XmlNode dateNode = rdfXml.SelectSingleNode("/rdf:RDF/rss:channel/dc:date", nsMgr);
        }
    }
}

43 Comments

Comments have been disabled for this content.