python - 在python中解析和转换嵌套的xml
问题描述
我有以下 xml 数据。
<transaction>
<date>20190415</date>
<ticket>303434037</ticket>
<value>15</value>
<notenders>01</notenders>
<tenderdetail>
<tendertype>00</tendertype>
<tenderamt>15</tenderamt>
</tenderdetail>
<item>
<receipeno>00001096</receipeno>
<price>7</price>
<qty>0001</qty>
<items>
<item>
<receipeno>00000786</receipeno>
<price>8</price>
<qty>0001</qty>
<items>
<item>
<receipeno>00000599</receipeno>
<price>0</price>
<qty>1</qty>
</item>
<item>
<receipeno>00000605</receipeno>
<price>0</price>
<qty>1</qty>
</item>
<item>
<receipeno>00000608</receipeno>
<price>0</price>
<qty>0004</qty>
</item>
</items>
</item>
<item>
<receipeno>10000043</receipeno>
<price>0</price>
<qty>0001</qty>
</item>
<item>
<receipeno>00000381</receipeno>
<price>7</price>
<qty>0001</qty>
<items>
<item>
<receipeno>00000607</receipeno>
<price>0</price>
<qty>1</qty>
</item>
</items>
</item>
</items>
</item>
</transaction>
我需要将其转换为表格格式。问题是每个标签内有许多嵌套分支。例如许多标签<item>
。<items>
与嵌套无关。我需要在另一个下面列出数据。
我想要的输出如下
+----------+--------+-------+-----------+------------+-----------+-----------+-------+-----+
| date | ticket | value | notenders | tendertype | tenderamt | receipeno | price | qty |
+----------+--------+-------+-----------+------------+-----------+-----------+-------+-----+
| 20190101 | 12345 | 15 | 1 | 0 | 15 | 1096 | 7 | 1 |
| 20190101 | 12345 | 15 | 1 | 0 | 15 | 786 | 8 | 1 |
| 20190101 | 12345 | 15 | 1 | 0 | 15 | 599 | 0 | 1 |
| 20190101 | 12345 | 15 | 1 | 0 | 15 | 605 | 0 | 1 |
| 20190101 | 12345 | 15 | 1 | 0 | 15 | 608 | 0 | 4 |
| 20190101 | 12345 | 15 | 1 | 0 | 15 | 143 | 0 | 1 |
| 20190101 | 12345 | 15 | 1 | 0 | 15 | 381 | 7 | 1 |
| 20190101 | 12345 | 15 | 1 | 0 | 15 | 607 | 0 | 1 |
+----------+--------+-------+-----------+------------+-----------+-----------+-------+-----+
我是 python 和 XML 解析的新手。因此,请指导我解决这个问题。...
解决方案
从必要的导入开始:
import pandas as pd
import xml.etree.ElementTree as et
import re
然后,要从要读取的标签中删除前导零,请定义以下函数:
def stripLZ(src):
return re.sub(r'^0+(?=\d)', '', src)
要读取源文件及其根元素,请执行:
tree = et.parse('transaction.xml')
root = tree.getroot()
要从根级别读取标签(而不是从item s 读取),请执行:
dt = root.find('date').text
tck = root.find('ticket').text
val = root.find('value').text
notend = stripLZ(root.find('notenders').text)
剩下的两个标签向下一层,所以从阅读它们的父标签开始:
tdet = root.find('tenderdetail')
并从中读取这些标签:
tendtyp = stripLZ(tdet.find('tendertype').text)
tendamt = tdet.find('tenderamt').text
请注意,我在这里使用了stripLZ函数(它将多次使用)。
现在有时间创建结果 DataFrame:
df_cols = ['date', 'ticket', 'value', 'notenders',
'tendertype', 'tenderamt', 'receipeno', 'price', 'qty']
df = pd.DataFrame(columns = df_cols)
并且可以使用iter方法执行加载循环:
for it in root.iter('item'):
rcp = it.find('receipeno').text
prc = it.find('price').text
qty = stripLZ(it.find('qty').text)
df = df.append(pd.Series([dt, tck, val, notend,
tendtyp, tendamt, rcp, prc, qty],
index = df_cols), ignore_index=True)
这个循环:
- 迭代所有项目标签,不管它们的深度。
- 从当前项目中读取 3 个标签。
- 在结果 DataFrame 中追加一行。