tutorial read parse open library etree datacamp python xml

read - xml etree python 3



¿Cómo puedo analizar XML en Python? (14)

xml.etree.ElementTree vs. lxml

Estos son algunos de los beneficios de las dos bibliotecas más usadas que me gustaría conocer antes de elegir entre ellas.

xml.etree.ElementTree:

  1. Desde la librería estándar : no hay necesidad de instalar ningún módulo.

lxml

  1. Escriba fácilmente la declaración XML : ¿necesita agregar, por ejemplo, standalone = "no"?
  2. Impresión bonita : puede tener un buen XML sangrado sin código adicional.
  3. Funcionalidad de Objectify : le permite usar XML como si estuviera tratando con una jerarquía normal de objetos de Python.

Tengo muchas filas en una base de datos que contiene xml y estoy tratando de escribir un script de Python que pase por esas filas y cuente cuántas instancias de un atributo de nodo en particular aparecen. Por ejemplo, mi árbol se ve como:

<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo>

¿Cómo puedo acceder a los atributos 1 y 2 en el XML utilizando Python?


Aquí un código muy simple pero efectivo usando cElementTree .

try: import cElementTree as ET except ImportError: try: # Python 2.5 need to import a different module import xml.etree.cElementTree as ET except ImportError: exit_err("Failed to import cElementTree from any known place") def find_in_tree(tree, node): found = tree.find(node) if found == None: print "No %s in file" % node found = [] return found # Parse a xml file (specify the path) def_file = "xml_file_name.xml" try: dom = ET.parse(open(def_file, "r")) root = dom.getroot() except: exit_err("Unable to open and parse input definition file: " + def_file) # Parse to find the child nodes list of node ''myNode'' fwdefs = find_in_tree(root,"myNode")

Fuente:

http://www.snip2code.com/Snippet/991/python-xml-parse?fromPage=1


Encuentro Python xml.dom y xml.dom.minidom bastante fáciles. Tenga en cuenta que DOM no es bueno para grandes cantidades de XML, pero si su entrada es bastante pequeña, esto funcionará bien.


Hay muchas opciones alla afuera. cElementTree ve excelente si la velocidad y el uso de la memoria son un problema. Tiene una sobrecarga muy pequeña en comparación con la simple lectura del archivo utilizando readlines lectura.

Las métricas relevantes se pueden encontrar en la tabla a continuación, copiada del cElementTree web cElementTree :

library time space xml.dom.minidom (Python 2.1) 6.3 s 80000K gnosis.objectify 2.0 s 22000k xml.dom.minidom (Python 2.4) 1.4 s 53000k ElementTree 1.2 1.6 s 14500k ElementTree 1.2.4/1.3 1.1 s 14500k cDomlette (C extension) 0.540 s 20500k PyRXPU (C extension) 0.175 s 10850k libxml2 (C extension) 0.098 s 16000k readlines (read as utf-8) 0.093 s 8850k cElementTree (C extension) --> 0.047 s 4900K <-- readlines (read as ascii) 0.032 s 5050k

Como lo señaló @jfs , cElementTree viene con Python:

  • Python 2: from xml.etree import cElementTree as ElementTree .
  • Python 3: from xml.etree import ElementTree (la versión C acelerada se usa automáticamente).

Podría sugerir declxml .

Revelación completa: escribí esta biblioteca porque buscaba una forma de convertir estructuras de datos XML y Python sin necesidad de escribir docenas de líneas de código imperativo de análisis / serialización con ElementTree.

Con declxml, usas procesadores para definir de forma declarativa la estructura de tu documento XML y cómo mapear entre XML y las estructuras de datos de Python. Los procesadores se utilizan para la serialización y el análisis, así como para un nivel básico de validación.

El análisis en las estructuras de datos de Python es sencillo:

import declxml as xml xml_string = """ <foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo> """ processor = xml.dictionary(''foo'', [ xml.dictionary(''bar'', [ xml.array(xml.integer(''type'', attribute=''foobar'')) ]) ]) xml.parse_from_string(processor, xml_string)

Lo que produce la salida:

{''bar'': {''foobar'': [1, 2]}}

También puede usar el mismo procesador para serializar datos a XML

data = {''bar'': { ''foobar'': [7, 3, 21, 16, 11] }} xml.serialize_to_string(processor, data, indent='' '')

Lo que produce la siguiente salida.

<?xml version="1.0" ?> <foo> <bar> <type foobar="7"/> <type foobar="3"/> <type foobar="21"/> <type foobar="16"/> <type foobar="11"/> </bar> </foo>

Si desea trabajar con objetos en lugar de diccionarios, puede definir procesadores para transformar datos hacia y desde objetos también.

import declxml as xml class Bar: def __init__(self): self.foobars = [] def __repr__(self): return ''Bar(foobars={})''.format(self.foobars) xml_string = """ <foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo> """ processor = xml.dictionary(''foo'', [ xml.user_object(''bar'', Bar, [ xml.array(xml.integer(''type'', attribute=''foobar''), alias=''foobars'') ]) ]) xml.parse_from_string(processor, xml_string)

Lo que produce la siguiente salida.

{''bar'': Bar(foobars=[1, 2])}


Puedes usar BeautifulSoup

from bs4 import BeautifulSoup x="""<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo>""" y=BeautifulSoup(x) >>> y.foo.bar.type["foobar"] u''1'' >>> y.foo.bar.findAll("type") [<type foobar="1"></type>, <type foobar="2"></type>] >>> y.foo.bar.findAll("type")[0]["foobar"] u''1'' >>> y.foo.bar.findAll("type")[1]["foobar"] u''2''


Python tiene una interfaz para el analizador xml expat.

xml.parsers.expat

Es un analizador que no valida, por lo que no se capturará el xml malo. 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.

stringofxml = """<foo> <bar> <type arg="value" /> <type arg="value" /> <type arg="value" /> </bar> <bar> <type arg="value" /> </bar> </foo>""" count = 0 def start(name, attr): global count if name == ''type'': count += 1 p = expat.ParserCreate() p.StartElementHandler = start p.Parse(stringofxml) print count # prints 4


Solo para agregar otra posibilidad, puedes usar Untangle , ya que es una simple biblioteca de objetos xml a python. Aquí tienes un ejemplo:

Instalación

pip install untangle

Uso

Tu archivo xml (un poco cambiado):

<foo> <bar name="bar_name"> <type foobar="1"/> </bar> </foo>

accediendo a los atributos con desenredar :

import untangle obj = untangle.parse(''/path_to_xml_file/file.xml'') print obj.foo.bar[''name''] print obj.foo.bar.type[''foobar'']

La salida será:

bar_name 1

Más información sobre desenredar se puede encontrar here .
También (si tienes curiosidad), puedes encontrar una lista de herramientas para trabajar con XML y Python here (también verás que las respuestas más comunes se mencionaron en las respuestas anteriores).


Sugiero ElementTree . Hay otras implementaciones compatibles de la misma API, como lxml y cElementTree en la biblioteca estándar de Python; pero, en este contexto, lo que agregan principalmente es aún más velocidad: la facilidad de programación depende de la API, que define ElementTree .

Después de crear una instancia de Element e partir del XML, por ejemplo, con la función XML , o analizando un archivo con algo como

import xml.etree.ElementTree e = xml.etree.ElementTree.parse(''thefile.xml'').getroot()

o cualquiera de las muchas otras formas mostradas en ElementTree , simplemente haces algo como:

for atype in e.findall(''type''): print(atype.get(''foobar''))

y similares, generalmente bastante simples, patrones de código.


Sugiero xmltodict por simplicidad.

Analiza su xml a un OrderedDict;

>>> e = ''<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo> '' >>> import xmltodict >>> result = xmltodict.parse(e) >>> result OrderedDict([(u''foo'', OrderedDict([(u''bar'', OrderedDict([(u''type'', [OrderedDict([(u''@foobar'', u''1'')]), OrderedDict([(u''@foobar'', u''2'')])])]))]))]) >>> result[''foo''] OrderedDict([(u''bar'', OrderedDict([(u''type'', [OrderedDict([(u''@foobar'', u''1'')]), OrderedDict([(u''@foobar'', u''2'')])])]))]) >>> result[''foo''][''bar''] OrderedDict([(u''type'', [OrderedDict([(u''@foobar'', u''1'')]), OrderedDict([(u''@foobar'', u''2'')])])])


XML

<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo>

PYTHON_CODE

import xml.etree.cElementTree as ET tree = ET.parse("foo.xml") root = tree.getroot() root_tag = root.tag print(root_tag) for form in root.findall("./bar/type"): x=(form.attrib) z=list(x) for i in z: print(x[i])

SALIDA:

foo 1 2


lxml.objectify es realmente simple.

Tomando su texto de muestra:

from lxml import objectify from collections import defaultdict count = defaultdict(int) root = objectify.fromstring(text) for item in root.bar.type: count[item.attrib.get("foobar")] += 1 print dict(count)

Salida:

{''1'': 1, ''2'': 1}


minidom es el más rápido y sencillo.

XML:

<data> <items> <item name="item1"></item> <item name="item2"></item> <item name="item3"></item> <item name="item4"></item> </items> </data>

PITÓN:

from xml.dom import minidom xmldoc = minidom.parse(''items.xml'') itemlist = xmldoc.getElementsByTagName(''item'') print(len(itemlist)) print(itemlist[0].attributes[''name''].value) for s in itemlist: print(s.attributes[''name''].value)

SALIDA

4 item1 item1 item2 item3 item4


import xml.etree.ElementTree as ET data = ''''''<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo>'''''' tree = ET.fromstring(data) lst = tree.findall(''bar/type'') for item in lst: print item.get(''foobar'')

Esto imprimirá el valor del atributo foobar.