Tengo muchas filas en una base de datos que contiene XML y estoy tratando de escribir un script de Python para contar instancias de un atributo de nodo particular.
Mi árbol se ve así:
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
¿Cómo puedo acceder a los atributos "1"
y "2"
en el XML usando Python?
Respuestas:
Sugiero
ElementTree
. Hay otras implementaciones compatibles de la misma API, comolxml
, ycElementTree
en la propia biblioteca estándar de Python; pero, en este contexto, lo que principalmente agregan es aún más velocidad: la facilidad de programación depende de la API, queElementTree
define.Primero construya una instancia de Element a
root
partir del XML, por ejemplo, con la función XML , o analizando un archivo con algo como:O cualquiera de las muchas otras formas que se muestran en
ElementTree
. Luego haz algo como:Y patrones de código similares, generalmente bastante simples.
fuente
lxml
agrega más que velocidad. Proporciona fácil acceso a información como el nodo principal, el número de línea en la fuente XML, etc. que puede ser muy útil en varios escenarios.Warning The xml.etree.ElementTree module is not secure against maliciously constructed data. If you need to parse untrusted or unauthenticated data see XML vulnerabilities.
minidom
es el más rápido y bastante sencillo.XML:
Pitón:
Salida:
fuente
item
directamente desde el nivel superior del documento? ¿no sería más limpio si le proporcionaras la ruta (data->items
)? porque, ¿qué pasaría si también tuvierasdata->secondSetOfItems
que también tuvieran nodos nombradositem
y quisieras enumerar solo uno de los dos conjuntos deitem
?Puedes usar BeautifulSoup :
fuente
BeautifulStoneSoup
está DEPRECIADO. Solo useBeautifulSoup(source_xml, features="xml")
ElementTree
, desafortunadamente no puedo analizar a menos que ajuste la fuente en algunos lugares, ¡peroBeautifulSoup
funcioné de inmediato sin ningún cambio!Hay muchas opciones alla afuera. cElementTree se ve excelente si la velocidad y el uso de memoria son un problema. Tiene muy poca sobrecarga en comparación con simplemente leer en el archivo usando
readlines
.Las métricas relevantes se pueden encontrar en la tabla a continuación, copiadas de sitio web cElementTree :
Como lo señaló @jfs ,
cElementTree
viene incluido con Python:from xml.etree import cElementTree as ElementTree
.from xml.etree import ElementTree
(la versión C acelerada se usa automáticamente).fuente
from xml.etree import cElementTree as ElementTree
. En Python 3:from xml.etree import ElementTree
(la versión C acelerada se usa automáticamente)ElementTree
para una tarea en particular. Para documentos que caben en la memoria, es mucho más fácil de usarminidom
y funciona bien para documentos XML más pequeños.Sugiero xmltodict por simplicidad.
Analiza tu XML a un OrderedDict;
fuente
result["foo"]["bar"]["type"]
es una lista de todos los<type>
elementos, por lo que aún funciona (aunque la estructura sea un poco inesperada).lxml.objectify es realmente simple.
Tomando su texto de muestra:
Salida:
fuente
count
almacena los recuentos de cada elemento en un diccionario con claves predeterminadas, para que no tenga que verificar la membresía. También puedes intentar mirarcollections.Counter
.Python tiene una interfaz para el analizador XML de expatriados.
Es un analizador no validado, por lo que no se detectará un XML incorrecto. Pero si sabe que su archivo es correcto, entonces esto es bastante bueno, y probablemente obtendrá la información exacta que desea y puede descartar el resto sobre la marcha.
fuente
Podría sugerir declxml .
Divulgación completa: escribí esta biblioteca porque estaba buscando una forma de convertir entre estructuras de datos XML y Python sin necesidad de escribir docenas de líneas de código de análisis / serialización imperativo con ElementTree.
Con declxml, utiliza procesadores para definir declarativamente la estructura de su documento XML y cómo mapear entre las estructuras de datos XML y Python. Los procesadores se utilizan tanto para la serialización y el análisis como para un nivel básico de validación.
Analizar las estructuras de datos de Python es sencillo:
Que produce la salida:
También puede usar el mismo procesador para serializar datos a XML
Que produce el siguiente resultado
Si desea trabajar con objetos en lugar de diccionarios, también puede definir procesadores para transformar datos hacia y desde objetos.
Que produce el siguiente resultado
fuente
Solo para agregar otra posibilidad, puede usar desenredar , ya que es una biblioteca simple de xml a python-object. Aquí tienes un ejemplo:
Instalación:
Uso:
Su archivo XML (un poco cambiado):
Accediendo a los atributos con
untangle
:El resultado será:
Se puede encontrar más información sobre desenredar en " desenredar ".
Además, si tiene curiosidad, puede encontrar una lista de herramientas para trabajar con XML y Python en " Python y XML ". También verá que los más comunes fueron mencionados en respuestas anteriores.
fuente
Aquí un código muy simple pero efectivo usando
cElementTree
.Esto es de " python xml parse ".
fuente
XML:
Código de Python:
Salida:
fuente
Esto imprimirá el valor del
foobar
atributo.fuente
xml.etree.ElementTree vs. lxml
Estas son algunas de las ventajas de las dos bibliotecas más utilizadas que me beneficiaría saber antes de elegir entre ellas.
xml.etree.ElementTree:
lxml
standalone="no"
?.node
.sourceline
permite obtener fácilmente la línea del elemento XML que está utilizando.fuente
Encuentro Python xml.dom y xml.dom.minidom bastante fácil. Tenga en cuenta que DOM no es bueno para grandes cantidades de XML, pero si su entrada es bastante pequeña, entonces funcionará bien.
fuente
No es necesario usar una API específica de lib si la usa
python-benedict
. Simplemente inicialice una nueva instancia desde su XML y adminístrela fácilmente, ya que es unadict
subclase.La instalación es fácil:
pip install python-benedict
Apoya y normaliza operaciones de E / S con muchos formatos:
Base64
,CSV
,JSON
,TOML
,XML
,YAML
yquery-string
.Está bien probado y de código abierto en GitHub .
fuente
fuente
Si la fuente es un archivo xml, digamos como esta muestra
puedes probar el siguiente código
La salida sería
fuente