XPath and XML Namespaces

It’s great that in C# code you can easily reference XML nodes using the XmlDocument’s built-in XPath support:

XmlNode titleNode = doc.SelectSingleNode("/html/head/title");

But have you ever run into the situation where you call SelectSingleNode or SelectNodes and you get back nothing when you can see there are nodes there? The problem might be that the document is using XML Namespaces.

Consider this XML snippet:

<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
<url>
<loc>http://blog.stevex.net/</loc>
</url>
</urlset>

If you attempt to retrieve nodes from this document using this code:

XmlNode urlNodes = doc.SelectNodes("/urlset/url");

You might expect to get back a set of all the url nodes, but instead you get back nothing.

To query into a document that uses namespaces, you need to use an XmlNamespaceManager. The namespace manager takes care of mapping a prefix to a namespace, and lets you associate the nodes in the query with particular namespaces.

The following code would query the sitemap.xml:

XmlNamespaceManager nsMgr = new XmlNamespaceManager(myXmlDoc.NameTable);
nsMgr.AddNamespace("sm", "http://www.google.com/schemas/sitemap/0.84");
XmlNode urlNodes = doc.SelectNodes("/sm:urlset/sm:url");

If a page uses multiple namespaces then you’d have multiple calls to AddNamespace with different prefixes. Your query string can include nodes from different namespaces.

12 Responses to “XPath and XML Namespaces”

  1. Martin Says:

    Thank you!! I have been struggling with this for a couple of hours and now (at last!) it is working!

  2. Makarad Says:

    I am having similar problem but by xml doc is having 2 namespace attributes as given below

    What should be XmlNamespaceManager for this one?

    Thanks
    MAKARAND

  3. SvendTofte Says:

    This was just what I needed to know. I have a document similar to this one, the documentation claims you can use “String.Empty”, for a default namespace (and thus, I assumed not need prefixes in the actual xpath expression).

    Thanks, was just about to waste another hour on this non-issue ;)

  4. Christian Palm Says:

    I think you have a typo in your example

    You write:
    XmlNamespaceManager nsMgr = new XmlNamespaceManager(myXmlDoc.NameTable);
    It shoud be, I think:
    XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);

  5. Brad Candell Says:

    Thank you SO MUCH.. I was about to give up all together on these stupid Namespaces! I found your document and had my code working within mere minutes..

    Thanks again!

    -Brad

  6. Lee Says:

    THANK YOU THANK YOU THANK YOU THANK YOU. You saved me from /wrists. I’ve been looking and looking at my XPath and KNEW it was right. I had no idea that the namespace would muck things up.

    Thanks again,
    Lee

  7. XML, XPath and XML Namespaces oh my… | The Sexy Gorilla Says:

    [...] was just about to /mywrists today when I found this post. I wanted to post to this blog to say thanks to SteveX for posting [...]

  8. joey Says:

    thanks for the info:

    my code required a different implementation…
    XmlNodeList urlLocNode = sitemap.SelectNodes(”/sm:urlset/sm:url/sm:loc”, nsMgr);

    1) SelectNodes returns a XmlNodeList not an XmlNode

    2) You need to use the overloaded version of the SelectNodes method to pass the XmlNamespaceManager object.

  9. XML, XPath and XML Namespaces oh my… « Everything I do Makes Me a Bitweiser Says:

    [...] XPath and XML Namespaces oh my… I was just about to /mywrists today when I found this post. I wanted to post to this blog to say thanks to SteveX for posting [...]

  10. suriya Says:

    Thanks Steve. This post is REALLY very useful. I was struggling to get xmlnode by using xpath from last two days and i got this post . Thanks once again.

  11. Corey Broderick Says:

    I thank you. My coworkers thank you. The cabinet I’ve been banging my head against for the last 2 hours thanks you. Cheers.

  12. chrisb Says:

    I only wish we could use the empty string for the namespace prefix like everyone else’s libraries use. It’s no fun rewriting tons of xpath to be compatible with Microsoft libraries. This took me days to figure out, and I found a MSFT reference page going back to ‘03 where they realize it’s wrong (”by design”) and I guess they’ll never make their libraries work the same as everyone else’s. I love their tools but things like this really chafe.

Leave a Reply