Saltar al contenido

¿Cómo uso los espacios de nombres xml con find / findall en lxml?

Solución:

Si root.nsmap contiene la table prefijo de espacio de nombres, entonces podría:

root.xpath('.//table:table', namespaces=root.nsmap)

findall(path) acepta {namespace}name sintaxis en lugar de namespace:name. Por lo tanto path debe ser preprocesado usando el diccionario de espacio de nombres para el {namespace}name formulario antes de pasarlo a findall().

Quizás lo primero que se debe notar es que los espacios de nombres están definidos en Nivel de elemento, no Nivel de documento.

Sin embargo, la mayoría de las veces, todos los espacios de nombres se declaran en el elemento raíz del documento (office:document-content aquí), lo que nos ahorra analizarlo todo para recopilar información interna xmlns ámbitos.

Entonces, un elemento nsmap incluye:

  • un espacio de nombres predeterminado, con None prefijo (no siempre)
  • todos los espacios de nombres de los antepasados, a menos que se anulen.

Si, como mencionó ChrisR, el espacio de nombres predeterminado no es compatible, puede usar una comprensión de dict para filtrarlo en una expresión más compacta.

Tiene una sintaxis ligeramente diferente para xpath y ElementPath.


Así que aquí está el código que podría usar para obtener todas las filas de su primera tabla (probado con: lxml=3.4.2):

import zipfile
from lxml import etree

# Open and parse the document
zf = zipfile.ZipFile('spreadsheet.ods')
tree = etree.parse(zf.open('content.xml'))

# Get the root element
root = tree.getroot()

# get its namespace map, excluding default namespace
nsmap = {k:v for k,v in root.nsmap.iteritems() if k}

# use defined prefixes to access elements
table = tree.find('.//table:table', nsmap)
rows = table.findall('table:table-row', nsmap)

# or, if xpath is needed:
table = tree.xpath('//table:table', namespaces=nsmap)[0]
rows = table.xpath('table:table-row', namespaces=nsmap)

Esta es una forma de obtener todos los espacios de nombres en el documento XML (y suponiendo que no haya conflicto de prefijos).

Utilizo esto cuando analizo documentos XML donde sé de antemano cuáles son las URL del espacio de nombres, y solo el prefijo.

        doc = etree.XML(XML_string)

        # Getting all the name spaces.
        nsmap = {}
        for ns in doc.xpath('//namespace::*'):
            if ns[0]: # Removes the None namespace, neither needed nor supported.
                nsmap[ns[0]] = ns[1]
        doc.xpath('//prefix:element', namespaces=nsmap)
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *