Как удалить новые строки в dataframe при записи в него xml?

#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/> ). В lxml list(element) возвращает дочерние узлы элемента, поэтому len() их должно быть 0, если дочерних элементов нет.