Как разобрать данные XML в список в Python - PullRequest
0 голосов
/ 12 октября 2019

Я пытаюсь принять ответ на вызов API и разобрать данные XML в список, но я борюсь с множественными дочерними / родительскими отношениями.

Я надеюсь экспортировать новый файл XML, который бывыровняйте каждый идентификатор задания и номер отслеживания, которые я затем мог бы импортировать в Excel.


Вот что у меня есть до сих пор

Исходный XML-файл выглядит так:

<project>
   <name>October 2019</name>
   <jobs>
      <job>
      <id>5654206</id>
      <tracking>
         <mailPiece>
             <barCode>00270200802095682022</barCode>
             <address>Accounts Payable,1661 Knott Ave,La Mirada,CA,90638</address>
             <status>En Route</status>
             <dateTime>2019-10-12 00:04:21.0</dateTime>
             <statusLocation>PONTIAC,MI</statusLocation>
        </mailPiece>
     </tracking>...

Код:

import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element, SubElement

tree = ET.parse('mailings.xml')
root = tree.getroot()
print(root.tag)

for x in root[1].findall('job'):
    id=x.find('id').text
    tracking=x.find('tracking').text
    print(root[1].tag,id,tracking)

В настоящее время скрипт возвращает следующее:

jobs 5654206 None
jobs 5654203 None

1 Ответ

0 голосов
/ 13 октября 2019

Отладка - ваш друг ...

Я борюсь с множественными отношениями между ребенком и родителями.

Правильный способ решить это самостоятельно - использоватьотладчик. Например, в VS Code после применения точки останова и запуска сценария с отладчиком он остановится на точке останова, и я смогу проверить все переменные в памяти и выполнить команды на консоли отладки, как если бы они были в моем сценарии. ,Выходные данные переменных окон выглядят так:

enter image description here

Существуют различные способы сделать это в командной строке или с REPL, как iPython, и т. Д. ., но я считаю, что использование отладки в современной среде IDE, такой как VS Code или PyCharm , определенно подходит. Их отладчики избавляют от необходимости перетекать операторы печати повсюду, чтобы проверить ваш код, переписать код, чтобы отобразить больше переменных, которые должны быть напечатаны на консоли, и т. Д.

Отладчик позволяет вам видеть все переменные какСнимок, точно так, как их видит интерпретатор Python, в любой момент выполнения вашего кода. Вы можете:

  • построчно просматривать ваш код и наблюдать за изменениями переменных в режиме реального времени в окне
  • настроить отдельное окно наблюдения только с теми переменными, которые вам нужныо
  • и настройке точек останова, которые будут иметь место только в том случае, если переменным заданы определенные значения и т. д.

Дочерняя иерархия с методом XML find

ПроверкаПо мере того, как я перебираю ваш код в переменных, кажется, что метод find () проводил детей внутри элемента на всех уровнях, а не только на верхнем уровне. Когда вы используете x.find('tracking'), он находит узлы mailPiece напрямую. Если вы напечатаете свойство tag вместо свойства text, вы увидите, что оно 'mailPiece' (см. Окна отладки выше).

Итак, один из способов решения вашей проблемы - сохранитькаждый элемент mailPiece как переменная, затем извлеките из него нужные атрибуты (например, BarCode, адрес и т. д.), используя find.

Вот некоторый код, который объединяет все это в объединенную иерархию списков. и словари, которые затем можно использовать для создания выходных данных Excel.

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

import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element, SubElement
from types import SimpleNamespace

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

jobs = []
for job in root[1].findall('job'):
    jobdict = {}
    jobdict['id'] = job.find('id').text
    jobdict['trackingMailPieces'] = []
    for tracking in job.find('tracking'):
        if tracking.tag == 'mailPiece':
            mailPieceDict = {}
            mailPieceDict['barCode'] = tracking.find('barCode').text
            mailPieceDict['address'] = tracking.find('address').text
            mailPieceDict['status'] = tracking.find('status').text
            mailPieceDict['dateTime'] = tracking.find('dateTime').text
            mailPieceDict['statusLocation'] = tracking.find('statusLocation').text
            jobdict['trackingMailPieces'].append(mailPieceDict)
    jobs.append(jobdict)

for job in jobs:
    print('Job ID: {}'.format(job['id']))
    for mp in job['trackingMailPieces']:
        print('  mailPiece:')
        for key, value in mp.items():
            print('    {} = {}'.format(key, value))

Результат:

Job ID: 5654206
  mailPiece:
    barCode = 00270200802095682022
    address = Accounts Payable,1661 Knott Ave,La Mirada,CA,90638
    status = En Route
    dateTime = 2019-10-12 00:04:21.0
    statusLocation = PONTIAC,MI

Вывод?

Я не говорил, что делать с выводом, поскольку это выходит за рамки этого вопроса, но рассмотрите возможность записи в файл CSV или даже напрямую в файл Excel, если выне нужно передавать на тОн XML для другой программы по какой-то причине. Существуют пакеты Python, которые обрабатывают написание файлов CSV и Excel.

Нет необходимости создавать промежуточный формат, которым вам нужно будет управлять после переноса его в Excel, например.

...