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.
November 14th, 2005 at 8:39 am
Thank you!! I have been struggling with this for a couple of hours and now (at last!) it is working!
November 22nd, 2005 at 12:42 am
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
January 22nd, 2006 at 10:48 am
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
January 29th, 2007 at 9:38 am
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);
February 19th, 2007 at 12:30 am
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
August 14th, 2007 at 8:41 pm
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
August 14th, 2007 at 8:48 pm
[...] 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 [...]
August 16th, 2007 at 1:18 pm
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.
April 1st, 2008 at 12:40 am
[...] 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 [...]