¿Cómo convertir un archivo XML en un bonito marco de datos de pandas?

Resuelto eoriu asked hace 9 años • 5 respuestas

Supongamos que tengo un XML como este:

<author type="XXX" language="EN" gender="xx" feature="xx" web="foobar.com">
    <documents count="N">
        <document KEY="e95a9a6c790ecb95e46cf15bee517651" web="www.foo_bar_exmaple.com"><![CDATA[A large text with lots of strings and punctuations symbols [...]
]]>
        </document>
        <document KEY="bc360cfbafc39970587547215162f0db" web="www.foo_bar_exmaple.com"><![CDATA[A large text with lots of strings and punctuations symbols [...]
]]>
        </document>
        <document KEY="19e71144c50a8b9160b3f0955e906fce" web="www.foo_bar_exmaple.com"><![CDATA[A large text with lots of strings and punctuations symbols [...]
]]>
        </document>
        <document KEY="21d4af9021a174f61b884606c74d9e42" web="www.foo_bar_exmaple.com"><![CDATA[A large text with lots of strings and punctuations symbols [...]
]]>
        </document>
    </documents>
</author>

Me gustaría leer este archivo XML y convertirlo en un DataFrame de pandas:

key                                         type     language    feature            web                         data
e95324a9a6c790ecb95e46cf15bE232ee517651      XXX        EN          xx      www.foo_bar_exmaple.com     A large text with lots of strings and punctuations symbols [...]
bc360cfbafc39970587547215162f0db             XXX        EN          xx      www.foo_bar_exmaple.com     A large text with lots of strings and punctuations symbols [...]
19e71144c50a8b9160b3cvdf2324f0955e906fce     XXX        EN          xx      www.foo_bar_exmaple.com     A large text with lots of strings and punctuations symbols [...]
21d4af9021a174f61b8erf284606c74d9e42         XXX        EN          xx      www.foo_bar_exmaple.com     A large text with lots of strings and punctuations symbols [...]

Esto es lo que ya intenté, pero recibo algunos errores y probablemente haya una forma más eficiente de realizar esta tarea:

from lxml import objectify
import pandas as pd

path = 'file_path'
xml = objectify.parse(open(path))
root = xml.getroot()
root.getchildren()[0].getchildren()
df = pd.DataFrame(columns=('key','type', 'language', 'feature', 'web', 'data'))

for i in range(0,len(xml)):
    obj = root.getchildren()[i].getchildren()
    row = dict(zip(['key','type', 'language', 'feature', 'web', 'data'], [obj[0].text, obj[1].text]))
    row_s = pd.Series(row)
    row_s.name = i
    df = df.append(row_s)

¿Alguien podría proporcionarme un mejor enfoque para este problema?

eoriu avatar Feb 01 '15 10:02 eoriu
Aceptado

Puede utilizar fácilmente xml(de la biblioteca estándar de Python) para convertir a un archivo pandas.DataFrame. Esto es lo que haría (al leer de un archivo, reemplácelo xml_datacon el nombre de su archivo u objeto de archivo):

import pandas as pd
import xml.etree.ElementTree as ET
import io

def iter_docs(author):
    author_attr = author.attrib
    for doc in author.iter('document'):
        doc_dict = author_attr.copy()
        doc_dict.update(doc.attrib)
        doc_dict['data'] = doc.text
        yield doc_dict

xml_data = io.StringIO(u'''YOUR XML STRING HERE''')

etree = ET.parse(xml_data) #create an ElementTree object 
doc_df = pd.DataFrame(list(iter_docs(etree.getroot())))

Si hay varios autores en su documento original o la raíz de su XML no es un author, entonces agregaría el siguiente generador:

def iter_author(etree):
    for author in etree.iter('author'):
        for row in iter_docs(author):
            yield row

y cambiar doc_df = pd.DataFrame(list(iter_docs(etree.getroot())))adoc_df = pd.DataFrame(list(iter_author(etree)))

Eche un vistazo al ElementTree tutorial proporcionado en la documentaciónxml de la biblioteca .

JaminSore avatar Feb 01 '2015 20:02 JaminSore

A partir de v1.3 , simplemente puedes usar:

pandas.read_xml(path_or_file)
iacob avatar Mar 25 '2021 08:03 iacob

Interviniendo para recomendar el uso de la biblioteca xmltodict . Manejó bastante bien su texto xml y lo he usado para ingerir un archivo xml con casi un millón de registros.

janoulle avatar Aug 29 '2020 02:08 janoulle