#python #xml #pandas #export-to-csv
#python #xml #pandas #экспорт в csv
Вопрос:
Я новичок здесь, и я пытался создать небольшой скрипт на Python для преобразования xml в csv. Основываясь на моем чтении различных сообщений здесь, в Stackoverflow, мне удалось придумать пример кода, который работает просто отлично.. Однако данные, с которыми я пытаюсь работать, имеют несколько слоев, и поэтому я не уверен, как извлечь данные на конечном уровне.
Ниже приведено, как выглядят данные:
<?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)
Однако этот код просто извлекает level2, а не ColA из level6.
Ожидаемый результат:
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'])
Ответ №1:
у вас проблема с отступом на
if len(elem):
Я думаю, это должно решить проблему.
Комментарии:
1.
if len(elem):
находится на базовом уровне, какой отступ вы предлагаете в этой строке?2. Что заставляет вас думать, что строка if () находится на базовой линии? Для меня это выглядит как часть элемента for в root: loop, поэтому в нем должен быть отступ.
Ответ №2:
Если я правильно понял ваш вопрос, вам нужно пройти по дереву 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
Выход:
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
Комментарии:
1. Сомнение: почему вы это переносите? Требовалось создать csv с заголовками в верхней строке, в отличие от заголовков в первом столбце, не так ли?