首页 > 解决方案 > 从 XML 中提取变量到 Pandas

问题描述

我正在将 XML 变量解析为 pandas 数据框。XML 文件看起来像( 此 XML 文件已为演示简化

<Instrm>
    <Rcrd>
        <FinPpt>
            <Id>BT0007YSAWK</Id>
            <FullNm>Turbo Car</FullNm>
            <Ccy>EUR</Ccy>
            <Cmmdty>false</Cmmdty>
        </FinPpt>
        <Issr>529900M2F7D5795H1A49</Issr>
        <Attrbts>
            <Authrty>US</Authrty>
            <Prd>
                <Dt>2002-03-20</Dt>
            </Prd>
            <Ven>NYSE</Ven>
        </Attrbts >
    </Rcrd>
</Instrm>
<Instrm>
    <Rcrd>
        <FinPpt>
            <Id>BX0009YNOYK</Id>
            <FullNm>Turbo truk</FullNm>
            <Ccy>EUR</Ccy>
            <Cmmdty>false</Cmmdty>
        </FinPpt>
        <Issr>58888M2F7D579536J4</Issr>
        <Attrbts>
            <Authrty>UK</Authrty>
            <Prd>
                <Dt>2002-04-21</Dt>
            </Prd>
            <Ven>BOX</Ven>
        </Attrbts >
    </Rcrd>
</Instrm>
...

我试图将此 XML 文件解析为一个数据框,其属性为列名,如下所示:

     Id          FullNm     Ccy   Cmmdty           Issr              Authrty      Dt         Ven   
BT0007YSAWK     Turbo Car   EUR   false    529900M2F7D5795H1A49       US       2002-03-20    NYSE
BX0009YNOYK     Turbo truk  EUR   false    58888M2F7D579536J4         UK       2002-04-21    BOX
 .....            ......    

但在我查看了一些帖子后仍然不知道如何。我所能做的就是在列表中提取 ID,比如

import xml.etree.ElementTree as ET
import pandas as pd
import sys

tree = ET.parse('sample.xml')
root = tree.getroot()
report = root[1][0][0]
records = report.findall('Instrm')
ids = []
for r in records:
    ids.append(r[0][0][0].text)

print(ids[0:100])

出去:

[BT0007YSAWK, BX0009YNOYK, …….]

我不太明白如何在这里使用“节点”。有人可以帮忙吗?谢谢你。

标签: pythonxmlpandasparsingxml-parsing

解决方案


假设已<root>发布 XML 中的节点没有命名空间,请考虑通过列表/字典理解构建字典并组合解析到所需节点的子字典(在 Python 3.5+ 中可用)。DataFrame()然后在返回的字典列表上调用构造函数。

data = [{**{el.tag:el.text.strip() for el in r.findall('FinPpt/*')},
         **{el.tag:el.text.strip() for el in r.findall('Issr')},
         **{el.tag:el.text.strip() for el in r.findall('Attrbts/*')},
         **{el.tag:el.text.strip() for el in r.findall('Attrbts/Prd/*')} 
        } for r in root.findall('Instrm/Rcrd')]
    
df = pd.DataFrame(data)

推荐阅读