2009-04-20 16 views
10

Mi requisito básico es obtener valor de elemento del archivo XML, he utilizado XMLDoxument.SelectSingleNode. Mi archivo XML contiene un espacio de nombres en el encabezado, así que he usado NameSpaceManager para agregar namespace-prefix y he usado prefix para obtener ese elemento en particular. Ahora, en mis archivos XML, los espacios de nombres están variando, no quiero hacer ningún código difícil, ¿hay alguna manera de que pueda encontrar todos los espacios de nombres y puedo agregarlo a NameSpaceManager?¿cómo puedo enumerar todo el espacio de nombres en XML?

Gracias.

+0

@Ruchita: El problema con este enfoque es que las declaraciones de espacios de nombres se pueden sobrescribir (en XML 1.0, la declaración de espacio de nombres predeterminada también se puede restablecer, en XML 1).1 todas las declaraciones del espacio de nombres) –

Respuesta

2

Su problema básico de recuperar espacios de nombres de un XmlDocument se puede resolver simplemente recuperando el NameTable del XmlDocument y creando un XmlNameSpaceManager desde él.

Sin embargo, si desea enumerar los espacios de nombres para otro propósito, debe verificar el método GetNamespacesInScope expuesto por la clase XmlNamespaceManager y la clase XPathNavigator.

Cuando se utiliza un XmlDocument, se puede obtener una XmlNamespaceManager de ella a través del siguiente código:

//Instantiate an XmlDocument object. 
XmlDocument xmldoc = new XmlDocument(); 

//Load XML file into the XmlDocument object. 
xmldoc.Load("C:\\myFile.xml"); 

//Instantiate an XmlNamespaceManager object. 
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmldoc.NameTable); 

// Retrieve the namespaces into a Generic dictionary with string keys. 
IDictionary<string, string> dic = nsMgr.GetNamespacesInScope(XmlNamespaceScope.All); 

// Iterate through the dictionary. 

... 

In this article, Scott Hanselman presenta una manera de utilizar este método para enumerar todos los espacios de nombres en un documento utilizando un XPathNavigator y usando un puente LINQ.

+2

Esto no parece funcionar para mí. Hay muchos elementos en el NameTable del documento, pero varios espacios de nombres definidos al principio del documento no se están agregando al XmlNamespaceManager. Sigo recibiendo "Namespace no definido" en mis llamadas a SelectNodes, a menos que agregue los espacios de nombres manualmente al administrador. Necesito una solución que lea con precisión los espacios de nombres definidos en el documento XML y los agregue a mi administrador de espacio de nombres para que no tenga que codificarlos. –

+0

@SeanWorle Es un poco tarde, pero echa un vistazo a [Obtener espacios de nombres de un documento XML con XPathDocument y LINQ a XML] (http://www.hanselman.com/blog/CommentView.aspx?guid=51861b63-526f-4572- ba84-2f24a1c7bd83), tal vez podría ayudarlo a usted o a alguien más. – ErikE

+1

El problema con este enfoque es que ignora las entradas "xmlns". –

7

Gracias por su respuesta rápida ...

creo que la versión .Net que está utilizando es debe ser más reciente. Estoy usando NET Framework 1.1 ... bastante viejo .. :(

Por el momento ,, i tienen un código de ejemplo como este .. con el mismo propósito ...

XmlNodeList _xmlNameSpaceList = _xmlDocument.SelectNodes(@"//namespace::*[not(. = ../../namespace::*)]"); 

      _xmlNSmgr = new XmlNamespaceManager(_xmlDocument.NameTable);   

      foreach(XmlNode nsNode in _xmlNameSpaceList) 
      { 
       _xmlNSmgr.AddNamespace(nsNode.LocalName,nsNode.Value); 
      } 

Cualquier se apreciará el comentario para agregar conocimiento a mi KB ... Gracias

+0

buen viejo XPath, funciona perfectamente bien, recupera todos los nodos con espacios de nombres. Gracias – zulucoda

-2

Si está buscando una forma rápida de evitar el problema del espacio de nombres, elimine las definiciones del espacio de nombres del Xml mediante un RegEx antes de hacer un XmlDocument .LoadXml (bla). Lo hago cuando analizo páginas XHTML en vivo. Toma el tiempo de carga de XmlDoc de 15 segundos a .15 segundos y lo hago para que no tenga que prefijar mis xpaths. .

13

Los espacios de nombres se pueden encontrar en cualquier lugar dentro del documento xml. Así que para extraer todos los espacios de nombres, lo cuenten en un XmlNamespaceManager hice lo siguiente:

public static XmlNamespaceManager getAllNamespaces(XmlDocument xDoc) 
{ 
    XmlNamespaceManager result = new XmlNamespaceManager(xDoc.NameTable); 

    IDictionary<string, string> localNamespaces = null; 
    XPathNavigator xNav = xDoc.CreateNavigator(); 
    while (xNav.MoveToFollowing(XPathNodeType.Element)) 
    { 
     localNamespaces = xNav.GetNamespacesInScope(XmlNamespaceScope.Local); 
     foreach (var localNamespace in localNamespaces) 
     { 
      string prefix = localNamespace.Key; 
      if (string.IsNullOrEmpty(prefix)) 
        prefix = "DEFAULT"; 

      result.AddNamespace(prefix, localNamespace.Value); 
     } 
    } 

    return result; 
} 

sólo prestar atención al caso del espacio de nombres por defecto. Redefiní el espacio de nombres predeterminado como prefijo "POR DEFECTO" porque tuve problemas al hacer SelectSingleNode utilizando el gestor de espacio de nombres devuelto anteriormente al consultar el espacio de nombres predeterminado. Yo fui mi solución. Espero que esto ayude

0

Ruchita publicó la solución de trabajo para XmlDocument. Pero quería hacer lo mismo con XDocument. Aquí es el mismo con XDocument:

var xml = XDocument.Load(filename); 
var xmlNameSpaceList = ((IEnumerable)xml.XPathEvaluate(@"//namespace::*[not(. = ../../namespace::*)]")).Cast<XAttribute>(); 
var xmlNSmgr = new XmlNamespaceManager(new NameTable()); 
foreach (var nsNode in xmlNameSpaceList) 
{ 
    xmlNSmgr.AddNamespace(nsNode.Name.LocalName, nsNode.Value); 
} 

Ahora puede utilizar XPath con espacios de nombres, por ejemplo, xml.XPathEvaluate("//test:p", xmlNSmgr).

Cuestiones relacionadas