XPathSelectElement siempre devuelve null

¿Por qué este Xpath no funciona con XDocument.XPathSelectElement?

Xpath:

//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2] 

XML

                   

C # Code:

 myXDocument.XPathSelectElement("//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2]", myXDocument.Root.CreateNavigator()); 

Cuando se utilizan espacios de nombres, estos también se deben usar en la consulta XPath. Su consulta XPath solo funcionaría contra elementos sin espacio de nombres (como se puede verificar eliminando el espacio de nombres de su XML).

Aquí hay un ejemplo que muestra cómo crear y pasar un administrador de espacio de nombres:

 var xml = ... XML from your post ...; var xmlReader = XmlReader.Create( new StringReader(xml) ); // Or whatever your source is, of course. var myXDocument = XDocument.Load( xmlReader ); var namespaceManager = new XmlNamespaceManager( xmlReader.NameTable ); // We now have a namespace manager that knows of the namespaces used in your document. namespaceManager.AddNamespace( "prefix", "http://www.MyNamespace.ca/MyPath" ); // We add an explicit prefix mapping for our query. var result = myXDocument.XPathSelectElement( "//prefix:Plugin/prefix:UI[1]/prefix:PluginPageCategory[1]/prefix:Page[1]/prefix:Group[1]/prefix:CommandRef[2]", namespaceManager ); // We use that prefix against the elements in the query. Console.WriteLine(result); //  element is printed. 

Espero que esto ayude.

Esto probablemente debería ser un comentario sobre la publicación de @ Cumbayah, pero parece que no puedo dejar comentarios sobre nada.

Probablemente sea mejor que uses algo como esto en lugar de usar XmlReader para obtener la tabla de nombres.

 var xml = ... XML from your post ...; var myXDocument = XDocument.Parse(xml); var namespaceManager = new XmlNamespaceManager(new NameTable()); namespaceManager.AddNamespace("prefix", "http://www.MyNamespace.ca/MyPath"); var result = ...; 

La manera más fácil en su caso es usar ejes XPath y la prueba de nodo para el nombre y la posición del nodo para seleccionar el elemento. Su selección de XPath:

 myXDocument.XPathSelectElement("//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2]", myXDocument.Root.CreateNavigator()); 

Se puede traducir fácilmente a:

 myXDocument.XPathSelectElement("/child::node()[local-name()='Plugin']/child::node()[local-name()='UI'][position()=1]/child::node()[local-name()='PluginPageCategory'][position()=1]/child::node()[local-name()='Page'][position()=1]/child::node()[local-name()='Group'][position()=1]/child::node()[local-name()='CommandRef'][position()=2]"); 

No es necesario crear y pasar XmlNamespaceManager como parámetro.

Hay una manera de hacerlo sin ningún cambio en xpath. La solución que he encontrado es eliminar el espacio de nombres al analizar XML en XDocument.

Aquí hay un ejemplo:

 var regex = @"(xmlns:?[^=]*=[""][^""]*[""])"; var myXDocument = XDocument.Parse(Regex.Replace("MyXmlContent", regex, "", RegexOptions.IgnoreCase | RegexOptions.Multiline)) 

Ahora que el espacio de nombres se ha ido, es fácil de manipular.