Python - Преобразование XML в CSV с использованием Python панд - PullRequest
3 голосов
/ 06 марта 2019

Я новичок здесь, и я пытался создать небольшой скрипт на python для преобразования xml в csv.Основываясь на прочтении различных постов здесь, в Stackoverflow, мне удалось придумать пример кода, который работает просто отлично. Однако данные, с которыми я пытаюсь работать, имеют несколько слоев, и поэтому я не уверен, как извлечь данные на листе.level.

Ниже приведены данные о том, как выглядят данные:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Transmission>
    <TransmissionBody>
        <level1>
            <level2>
                <level3>
                    <level4>
                        <level5>
                            <level6>
                                <ColA>ABC</ColA>
                                <ColB>123</ColB>
                            </level6>
                        </level5>
                    </level4>
                </level3>
            </level2>
        </level1>
    </TransmissionBody>
</Transmission>

Я пытаюсь использовать приведенный ниже код для преобразования XML в CSV

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

tree = ET.parse('file.xml')
root = tree.getroot()
final = {}
for elem in root:
    if len(elem):
        for c in elem.getchildren():
            final[c.tag] = c.text
    else:
        final[elem.tag] = elem.text

df = pd.DataFrame([final])
df.to_csv('file.csv)

Этот код, однако, просто получает уровень 2, а не ColA с уровня 6.

Ожидаемый результат :

Transmission,TransmissionBody,level1,level2,level3,level4,level5,level6,ColA,ColB
,,,,,,,,ABC,123
,,,,,,,,DEF,456

Обновленный код :

allFiles = glob.glob(folder)
for file in allFiles:
    xmllist = [file]
    for xmlfile in xmllist:
        tree = ET.parse(xmlfile)
        root = tree.getroot()

        def f(elem, result):
            result[elem.tag] = elem.text
            cs = elem.getchildren()
            for c in cs:
                result = f(c, result)
            return result

         d = f(root, {})
         df = pd.DataFrame(d, index=['values'])

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

у вас есть проблема с отступом на

if len(elem):

Я думаю, это должно решить ее.

1 голос
/ 06 марта 2019

Если я правильно понял ваш вопрос, вам нужно пройтись по дереву XML, так что вы, вероятно, захотите иметь рекурсивную функцию, которая делает это.Примерно так:

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

tree = ET.parse('file.xml')
root = tree.getroot()

def f(elem, result):
    result[elem.tag] = elem.text
    cs = elem.getchildren()
    for c in cs:
        result = f(c, result)
    return result

d = f(root, {})
df = pd.DataFrame(d, index=['values']).T
df

Out:

    values
Transmission    \n
TransmissionBody    \n
level1  \n
level2  \n
level3  \n
level4  \n
level5  \n
level6  \n
ColA    ABC
ColB    123

Обновление: Вот когда нам нужно сделать это для нескольких файлов XML.Я добавил еще один файл, похожий на оригинальный, с ColA, строки ColB заменены на

<ColA>DEF</ColA>
<ColB>456</ColD>

Вот код:

def f(elem, result):
    result[elem.tag] = elem.text
    cs = elem.getchildren()
    for c in cs:
        result = f(c, result)
    return result

result = {}
for file in glob.glob('*.xml'):
    tree = ET.parse(file)
    root = tree.getroot()
    result = f(root, result)

df = pd.DataFrame(result, index=['values']).T
df

И вывод:

                    0    1
Transmission       \n   \n
TransmissionBody   \n   \n
level1             \n   \n
level2             \n   \n
level3             \n   \n
level4             \n   \n
level5             \n   \n
level6             \n   \n
ColA              ABC  DEF
ColB              123  456
...