#python #python-3.x #xml #pandas #dataframe
#python #python-3.x #xml #панды #dataframe
Вопрос:
Я пытаюсь написать xml
ответ из an api
, повторяя tag
TrackingEvent и сохраняя в dataframe
:
xml
Ответ выглядит так :
<?xml version="1.0" encoding="UTF-8"?>
<TrackingResult>
<Events>
<TrackingEvent>
<DateTimeStamp>202010</DateTimeStamp>
<Event>Delivered</Event>
<ExtraInfo>02921</ExtraInfo>
</TrackingEvent>
<TrackingEvent>
<DateTimeStamp>202010</DateTimeStamp>
<Event>Delivery today</Event>
<ExtraInfo>31916</ExtraInfo>
</TrackingEvent>
</Events>
<Signatures />
<Errors />
</TrackingResult>
Я записываю это в фрейм данных, используя этот код :
response_status = requests.get(url, headers = headers)
print(type(response_status)) #<class 'requests.models.Response'>
print(type(response_status.content)) #<class 'bytes'>
tree = ET.fromstring(response_status.content)
for child in tree.iter('TrackingEvent'):
for elem in child.iter():
data = {str(elem.tag):[elem.text]}
if str(elem.text)=='None' :continue
response_df = pd.DataFrame(data)
consolidated_list.append(response_df)
consolidated_df = pd.concat(consolidated_list,ignore_index=True)
print(consolidated_df)
Это результат dataframe
, который я получаю :
DateTimeStamp Event ExtraInfo
202010
Delivered
02921
202010
Delivery today
31916
Я хочу удалить эти пустые пробелы, чтобы поместить одну дочернюю итерацию в одну строку dataframe
ожидаемый результат:
DateTimeStamp Event ExtraInfo
202010 Delivered 02921
202010 Delivery today 31916
Ответ №1:
Я бы рекомендовал создать dict в цикле, а затем создать dataframe на основе этого dict. Вот пример:
xml = '''<?xml version="1.0" ?>
<TrackingResult>
<Events>
<TrackingEvent>
<DateTimeStamp>202010</DateTimeStamp>
<Event>Delivered</Event>
<ExtraInfo>02921</ExtraInfo>
</TrackingEvent>
<TrackingEvent>
<DateTimeStamp>202010</DateTimeStamp>
<Event>Delivery today</Event>
<ExtraInfo>31916</ExtraInfo>
</TrackingEvent>
</Events>
<Signatures />
<Errors />
</TrackingResult>'''
from lxml import etree as ET
import pandas as pd
from collections import defaultdict
d = defaultdict(list)
tree = ET.fromstring(xml)
for child in tree.iter('TrackingEvent'):
for elem in child.iter():
if (elem.text is not None and str(elem.text).strip() != ''):
d[elem.tag].append(elem.text.strip())
else:
if len(list(elem)) == 0:
d[elem.tag].append(None)
df = pd.DataFrame(d)
print(df)
Вывод:
DateTimeStamp Event ExtraInfo
0 202010 Delivered 02921
1 202010 Delivery today 31916
Комментарии:
1.
d[elem.tag].append(elem.text.strip()) AttributeError: 'NoneType' object has no attribute 'strip'
2. Обновленный ответ с проверками на отсутствие типа и XML-листов.
3. это сработало .. спасибо .. Не могли бы вы расширить
else
часть?4. В
else
части мы проверяем, является ли элемент листом с точки зрения XML (т. Е. Не Имеет дочерних элементов). Это позволяет пропускать, напримерTrackingEvent
, элементы, но обрабатывать ситуации, когда один изDateTimeStamp
Event
ExtraInfo
тегов, или является пустым или самозакрывающимся (например, <Event/> ). В lxmllist(element)
возвращает дочерние узлы элемента, поэтомуlen()
их должно быть 0, если дочерних элементов нет.