Friday, July 20, 2007

XPath, C#, .NET, and namespaces.

So I was trying to use XPath to search this XML document I'm working with using System.Xml in C#/.Net. The obvious thing to use for me was the method SelectSingleNode(). I had read around that you had to be very careful with default namespaces using XPath 1.0 in .Net. In summary, all namespaces must have a prefix, even the default one. You just have to make a prefix up for the default namespace. I chose the imaginative "default" prefix.

Anyway, these were the first couple lines of my XML doc:


<?xml version="1.0" encoding="utf-8"?>
<Specification Standard="802.16e Cor2, 2007" VersionDate="2007-06-21" Company="Sanjole Inc." Author="Min Xu" xmlns="http://sanjole.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xsi:schemaLocation="http://sanjole.com/ Sanjole.xsd">


So I have a default namespace. I used the following code, which didn't work:

XmlDocument xmlSpecDoc = new XmlDocument();
xmlSpecDoc.Load(xmlSpecFileName);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlSpecDoc.NameTable);
nsmgr.AddNamespace("default", "http://sanjole.com");
nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
nsmgr.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");
nsmgr.AddNamespace("msxsl", "urn:schemas-microsoft-com:xslt");
XmlElement root = xmlSpecDoc.DocumentElement;
XmlNode messageNode = root.SelectSingleNode("/default:Specification", nsmgr);


This returned a messageNode of null, even though it's obviously in the document.

Can you find the bug? Me neither, but my colleague found it... look closely at the default namespace. Give up? It should have been:

nsmgr.AddNamespace("default", "http://sanjole.com/");


That's right... watch your trailing "/"'s. I'm won't reveal how long I was messing with this. Let's just say it was in the range of "hours".

No comments: