Python: ElementTree, obtiene la cadena de espacio de nombres de un elemento

Este archivo XML se llama example.xml :

   14.0.0 .com.foobar.flubber uberportalconf 13-SNAPSHOT pom Environment for UberPortalConf This is the description  11 9 6 2    

Si cargó example.xml y lo analizo con ElementTree, puedo ver que su espacio de nombres es http://maven.apache.org/POM/4.0.0 .

 >>> from xml.etree import ElementTree >>> tree = ElementTree.parse('example.xml') >>> print tree.getroot()  

No he encontrado un método al que llamar para obtener solo el espacio de nombres de un Element sin tener que recurrir al análisis del str(an_element) de un Elemento. Parece que tiene que haber una mejor manera.

El espacio de nombres debe estar en Element.tag justo antes de la etiqueta “actual”:

 >>> root = tree.getroot() >>> root.tag '{http://maven.apache.org/POM/4.0.0}project' 

Para saber más sobre los espacios de nombres, eche un vistazo a ElementTree: Trabajar con espacios de nombres y nombres calificados .

Esta es una tarea perfecta para una expresión regular .

 import re def namespace(element): m = re.match('\{.*\}', element.tag) return m.group(0) if m else '' 

No estoy seguro de si esto es posible con xml.etree , pero aquí es cómo podría hacerlo con lxml.etree :

 >>> from lxml import etree >>> tree = etree.parse('example.xml') >>> tree.xpath('namespace-uri(.)') 'http://maven.apache.org/POM/4.0.0' 

Sin usar expresiones regulares:

 >>> root  >>> root.tag.split('}')[0].strip('{') 'http://www.google.com/schemas/sitemap/0.84' 

Creo que será más fácil echar un vistazo a los atributos:

 >>> root.attrib {'{http://www.w3.org/2001/XMLSchema-instance}schemaLocation': 'http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'} 

combinando algunas de las respuestas anteriores, creo que el código más corto es

 theroot = tree.getroot() theroot.attrib[theroot.keys()[0]] 

El lxml.xtree biblioteca lxml.xtree tiene un diccionario llamado nsmap , que muestra todo el espacio de nombres que está en uso en el ámbito de la etiqueta actual.

 >>> item = tree.getroot().iter().next() >>> item.nsmap {'md': 'urn:oasis:names:tc:SAML:2.0:metadata'} 

La respuesta corta es:

 ElementTree._namspace_map[ElementTree._namspace_map.values().index('')] 

pero solo si has estado llamando

 ElementTree.register_namespace(prefix,uri) 

en respuesta a cada evento == “start-ns” recibido mientras iteraba a través del resultado de

 ET.iterparse(...) 

y te registraste para “start-ns”

La respuesta a la pregunta “¿cuál es el espacio de nombres predeterminado?”, Es necesario aclarar dos puntos:

(1) Las especificaciones XML dicen que el espacio de nombres predeterminado no es necesariamente global en todo el árbol, sino que el espacio de nombres predeterminado se puede volver a declarar en cualquier elemento de la raíz y se hereda hacia abajo hasta que se cumpla con otra statement de espacios de nombres predeterminada.

(2) El módulo ElementTree puede (de facto) manejar documentos similares a XML que no tienen un espacio de nombres predeterminado de raíz, -si no tienen uso de espacio de nombres en ningún lugar del documento. (* puede haber condiciones menos estrictas, por ejemplo, es decir “si” y no necesariamente “iff”).

Probablemente también vale la pena considerar “para qué lo quieres?” Tenga en cuenta que los archivos XML pueden ser semánticamente equivalentes, pero sintácticamente muy diferentes. Por ejemplo, los siguientes tres archivos son semánticamente equivalentes, pero A.xml tiene una statement de espacio de nombres predeterminada, B.xml tiene tres y C.xml no tiene ninguno.

 A.xml:     B.xml:     C.xml: <{http://A}a> <{http://B0}b/> <{http://B1}b/>  

El archivo C.xml es la representación sintáctica expandida canónica presentada a las funciones de búsqueda de ElementTree.

Si está seguro a priori de que no habrá colisiones en el espacio de nombres, puede modificar las tags de elementos mientras analiza como se explica aquí: Módulo de ElementTree de Python: Cómo ignorar el espacio de nombres de los archivos XML para ubicar el elemento correspondiente al usar el método “encontrar”. “encuentra todos”