У меня есть следующий формат xml:
<?xml version = "1.0" encoding = "UTF-8"?>
<results>
<run>
<information>
<logfile>s.log</logfile>
<version>33</version>
<mach>1</mach>
<problemname>mm1</problemname>
<timestamp>20201218.165122.053486</timestamp>
</information>
<controls>
<item>VARS</item>
</controls>
<result>
<status>4</status>
<time>3</time>
<obj>1.0</obj>
<gap>0.15</gap>
</result>
</run>
</results>
У меня есть пример кода ниже, чтобы разобрать этот файл после прочтения этого поста Как преобразовать файл XML в красивый фрейм данных pandas?, но возвращает None. Однако мой вопрос заключается в том, есть ли быстрый способ создать фрейм данных, который содержит индекс из значения (т. е. VARS) и 4 столбца, т. е. статус, время, объект и разрыв.
import pandas as pd
from xml.etree import ElementTree as et
root = (et.parse('test.xml').getroot()).getchildren()
tags = {"tags":[]}
for elem in root:
tag = {}
tag["status"] = elem.attrib['status']
tag["time"] = elem.attrib['time']
tag["obj"] = elem.attrib['obj']
tag["gap"] = elem.attrib['gap']
tags["tags"]. append(tag)
df_users = pd.DataFrame(tags["tags"])
df_users.head()
Это результат, который я ищу:
status time obj gap
VARS 4 3 1.0 0.15
Также см. Как преобразовать файл XML в красивый фрейм данных pandas?
Ваш xml неправильно сформирован - например, где рядом <run> и <results>?
@ДжекФлитинг. Спасибо. Только что обновил это.
@noah Спасибо, что поделились публикацией. Обновил мой вопрос в соответствии с этим.
Попробуйте понять, почему вы получаете None. В том, что нет elem в root? Если это так, то это проблема синтаксического анализа xml. Код, касающийся создания панд, и так должен быть достаточно быстрым.
Можете ли вы использовать lxml вместо xml.etree? Это просто проще.
Отвечает ли это на ваш вопрос? Как преобразовать файл XML в красивый фрейм данных pandas?






Я думаю, вам все еще нужно пройти через etree, чтобы извлечь фрагменты с помощью xml.
import pandas as pd
from xml.etree import ElementTree as et
root = et.parse('test.xml').getroot()
results = []
for ele in eles.findall('run'):
# assumed each run contains only one control item
control = ele.find('controls').find('item').text
# extract each run result and save it in the results
for attr in list(ele.find('result')):
result = {}
result['control'] = control
result[attr.tag] = attr.text
results.append(result)
# at last, convert into dataframe and set control as index
results = pd.DataFrame(results)
results = results.set_index('control')
Как здесь создается "eles"?
Мы можем использовать методы findall и find из ElementTree для извлечения нужных нам элементов (дочерние элементы result в качестве столбцов и controls/item в качестве индекса):
pd.DataFrame({x.tag: x.text for x in et.findall('./run/result//')},
index = [et.find('./run/controls/item').text])
Выход:
status time obj gap
VARS 4 3 1.0 0.15
Обратите внимание, что статус не находится под root, но вы пытаетесь найти его под root.
status находится под родителем result.
Вам нужно рекурсивно проверять статус под дочерними элементами.
Обратитесь к документации. Подробно рассказывается о методах с образцами. findall полезен, как предложили другие.
Что etree выводит для вас? Нас как бы не волнует xml, мы заботимся о выводе etree, так как это то, что вы пытаетесь создать df.