XPathSelectElement restituisce sempre null

Perché questo Xpath non funziona usando XDocument.XPathSelectElement?

XPath:

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

XML

                   

Codice C #:

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

Quando vengono utilizzati gli spazi dei nomi, questi devono essere utilizzati anche nella query XPath. La tua query XPath funzionerà solo contro elementi senza spazio dei nomi (come può essere verificato rimuovendo lo spazio dei nomi dal tuo XML).

Ecco un esempio che mostra come si crea e si passa un gestore di spazi dei nomi:

 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. 

Spero che questo ti aiuti.

Questo dovrebbe probabilmente essere un commento sul post di @ Cumbayah, ma non riesco a lasciare commenti su nulla.

Probabilmente stai meglio usando qualcosa di simile invece di usare XmlReader per ottenere il nametable.

 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 = ...; 

Il modo più semplice nel tuo caso è utilizzare gli assi XPath e il test del nodo per il nome e la posizione del nodo per selezionare l’elemento. La tua selezione XPath:

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

Può essere facilmente tradotto in:

 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]"); 

Non è necessario creare e passare XmlNamespaceManager come parametro.

C’è un modo per farlo senza alcuna modifica a xpath. La soluzione che ho trovato è di rimuovere lo spazio dei nomi durante l’analisi dell’XML in XDocument.

Ecco un esempio:

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

Ora che lo spazio dei nomi è scomparso, è più facile da manipolare.