如何在Python中将XML数据解析为列表

时间:2019-10-12 20:44:56

标签: python python-3.x xml-parsing elementtree

我试图获取一个API调用响应并将XML数据解析为列表,但是我正努力处理多个子/父关系。

我希望导出一个新的XML文件,该文件将排列每个作业ID和跟踪编号,然后将其导入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 :(得分:0)

调试是您的朋友...

  

我正在为多个孩子/父母之间的关系而苦苦挣扎。

自行解决此问题的正确方法是使用调试器。例如,使用VS Code,在应用断点并使用调试器运行脚本之后,它将在断点处停止,我可以检查内存中的所有变量,并在调试控制台上运行命令,就像它们在我的脚本中一样。可变窗口输出如下所示:

enter image description here

有多种方法可以在命令行上执行,也可以使用REPL(如iPython等)来执行此操作,但是我发现在现代IDE环境(如 VS Code PyCharm 绝对是必经之路。他们的调试器消除了在任何地方添加胡椒粉语句来测试代码,重写代码以暴露更多必须打印到控制台的变量的需求,等等。

调试器允许您在代码执行中的任何时候,将所有变量视为快照,确切地说是Python解释器如何查看它们。您可以:

  • 逐行浏览代码,并在窗口中实时查看变量的变化
  • 使用仅关注的变量设置单独的监视窗口
  • 以及仅在将变量设置为特定值等情况下才会发生的设置断点。

具有XML find方法的子层次结构

在我逐步检查代码时检查变量,似乎find()方法正在所有级别(而不只是在顶层)上遍历Element中的子级。当您使用x.find('tracking')时,它将直接找到mailPiece节点。如果打印tag属性而不是text属性,您将看到它是'mailPiece'(请参见上面的调试窗口)。

因此,解决问题的一种方法是将每个mailPiece元素存储为一个变量,然后使用查找从中提取所需的各个属性(即条形码,地址等)。

这是一些代码,可将所有这些信息拉入列表和字典的组合层次结构中,然后可用于构建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后就需要进行操作。