Xml-SelectNodes con el espacio de nombres predeterminado a través de XmlNamespaceManager no funciona como se esperaba

Tengo algunos xml con espacio de nombres predeterminado

 

y quiere contar el número de

¿Cómo debo definir

 XmlNamespaceManager nsmgr = ???? Assert.AreEqual(2, doc.SelectNodes("//b", nsmgr).Count); 

para que la afirmación se haga realidad?

Lo he intentado hasta ahora (usando nunit):

 [Test] [Ignore("Why does this not work?")] public void __DoesNotWork_TestSelectWithDefaultNamespace() { // xml to parse with defaultnamespace string xml = @""; XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); // fails because xpath does not have the namespace //!!!! Assert.AreEqual(2, doc.SelectNodes("//b").Count); // using XPath defaultnamespace XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); nsmgr.AddNamespace("", "urn:test.Schema"); // This will fail with dotnet 3.5sp1. Why? //!!!! Assert.AreEqual(2, doc.SelectNodes("//b", nsmgr).Count); } [Test] public void TestSelectWithoutNamespaces_Ok() { // xml to parse without namespace string xml = @""; XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); // works ok Assert.AreEqual(2, doc.SelectNodes("//b").Count); // works ok XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); Assert.AreEqual(2, doc.SelectNodes("//b", nsmgr).Count); } [Test] public void TestSelectWithNamespacesPrefixed_Ok() { // xml to parse with defaultnamespace string xml = @""; XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); // using XPath namespace via alias "t". works ok but xpath is to complicated XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); nsmgr.AddNamespace("t", doc.DocumentElement.NamespaceURI); Assert.AreEqual(2, doc.SelectNodes("//t:b", nsmgr).Count); } 

 // This will fail with dotnet 3.5sp1. Why? //!!!! Assert.AreEqual(2, doc.SelectNodes("//b", nsmgr).Count); 

Esta es una pregunta frecuente En XPath se supone que cualquier nombre no prefijado está en “sin espacio de nombres”. Para seleccionar elementos que pertenecen a un espacio de nombres, en cualquier expresión XPath, sus nombres deben estar prefijados con un prefijo asociado a este espacio de nombres. El método AddNamespace() sirve exactamente para este propósito. Crea un enlace entre un espacio de nombre específico y un prefijo específico. Luego, si este prefijo se usa en una expresión XPath, se puede seleccionar el elemento con el prefijo.

Está escrito en la especificación XPath W3C : “Un QName en la prueba de nodo se expande en un nombre expandido usando las declaraciones de espacio de nombres del contexto de expresión. Esta es la misma forma en que se hace la expansión para los nombres de tipos de elementos en las tags de inicio y final excepto que no se usa el espacio de nombres predeterminado declarado con xmlns: si QName no tiene un prefijo, entonces el URI del espacio de nombres es nulo “.

Vea esto en: w3.org/TR/xpath/#node-tests .

Por lo tanto, cualquier nombre no prefijado se considera que está en “sin espacio de nombres”. En el documento XML proporcionado no hay elementos b en “sin espacio de nombres” y esta es la razón por la cual la expresión XPath //b no selecciona ningún nodo.

Uso :

 XmlNamespaceManager nsmanager = new XmlNamespaceManager(doc.NameTable); nsmanager.AddNamespace("x", "urn:test.Schema"); 

y más tarde :

 Assert.AreEqual(2, doc.SelectNodes("//x:b", nsmanager).Count); 

Recuerde : El objective de registrar el espacio de nombres es poder usar el prefijo (en este caso x ) en cualquier expresión XPath.