Using Xpath With Default Namespace in C#

前端 未结 13 1510
别那么骄傲
别那么骄傲 2020-11-22 03:02

I\'ve got an XML document with a default namespace. I\'m using a XPathNavigator to select a set of nodes using Xpath as follows:

XmlElement myXML = ...;           


        
13条回答
  •  心在旅途
    2020-11-22 03:59

    I encountered a similar problem with a blank default namespace. In this example XML, I have a mix of elements with namespace prefixes, and a single element (DataBlock) without:

    
     
      
       7
      
      
       Value
       
       
        Value
       
      
     
    
    

    I attempted to use an XPath that worked in XPath Visualizer, but did not work in my code:

      XmlDocument doc = new XmlDocument();
      doc.Load( textBox1.Text );
      XPathNavigator nav = doc.DocumentElement.CreateNavigator();
      XmlNamespaceManager nsman = new XmlNamespaceManager( nav.NameTable );
      foreach ( KeyValuePair nskvp in nav.GetNamespacesInScope( XmlNamespaceScope.All ) ) {
        nsman.AddNamespace( nskvp.Key, nskvp.Value );
      }
    
      XPathNodeIterator nodes;
    
      XPathExpression failingexpr = XPathExpression.Compile( "/src:SRCExample/DataBlock/a:DocID/a:IdID" );
      failingexpr.SetContext( nsman );
      nodes = nav.Select( failingexpr );
      while ( nodes.MoveNext() ) {
        string testvalue = nodes.Current.Value;
      }
    

    I narrowed it down to the "DataBlock" element of the XPath, but couldn't make it work except by simply wildcarding the DataBlock element:

      XPathExpression workingexpr = XPathExpression.Compile( "/src:SRCExample/*/a:DocID/a:IdID" );
      failingexpr.SetContext( nsman );
      nodes = nav.Select( failingexpr );
      while ( nodes.MoveNext() ) {
        string testvalue = nodes.Current.Value;
      }
    

    After much headscratching and googling (which landed me here) I decided to tackle the default namespace directly in my XmlNamespaceManager loader by changing it to:

      foreach ( KeyValuePair nskvp in nav.GetNamespacesInScope( XmlNamespaceScope.All ) ) {
        nsman.AddNamespace( nskvp.Key, nskvp.Value );
        if ( nskvp.Key == "" ) {
          nsman.AddNamespace( "default", nskvp.Value );
        }
      }
    

    So now "default" and "" point to the same namespace. Once I did this, the XPath "/src:SRCExample/default:DataBlock/a:DocID/a:IdID" returned my results just like I wanted. Hopefully this helps to clarify the issue for others.

提交回复
热议问题