首页 > 解决方案 > 在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 解析的新手。因此,请指导我解决这个问题。...

标签: pythonxmlpandas

解决方案


从必要的导入开始:

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 中追加一行。

推荐阅读