为了账号安全,请及时绑定邮箱和手机立即绑定

如何将xml解析为具有同级元素的表?

如何将xml解析为具有同级元素的表?

犯罪嫌疑人X 2023-06-27 18:29:35
我的 xml 看起来像这样:xml = """<portfolio>    <assets>600000</assets>    <assetClassDetails>        <assetClassName>Bonds</assetClassName>        <assetAmount>100000</assetAmount>    </assetClassDetails>    <assetClassDetails>        <assetClassName>Equities</assetClassName>        <assetAmount>500000</assetAmount>    </assetClassDetails>    <rateOfReturn>6.3</rateOfReturn></portfolio>"""我通过这样做将每个元素解析到一个表中:root = etree.fromstring(xml)tag = []text = []parent = []double_parent = []for element in root.iter():    try:        element_parent = element.getparent().tag    except AttributeError:        element_parent = 'none'    try:        element_double_parent = element.getparent().getparent().tag    except AttributeError:        element_double_parent = 'none'    tag.append(element.tag)    text.append(element.text)    parent.append(element_parent)    double_parent.append(element_double_parent)df = pd.DataFrame({'tag' : tag, 'text' : text, 'parent' : parent, 'double_parent' : double_parent})结果是这样的:tag                 text      parent            double_parentportfolio           \n        none              noneassets              600000    portfolio         noneassetClassDetails   \n        portfolio         noneassetClassName      Bonds     assetClassDetails portfolioassetAmount         100000    assetClassDetails portfolioassetClassDetails   \n        portfolio         noneassetClassName      Equities  assetClassDetails portfolioassetAmount         500000    assetClassDetails portfoliorateOfReturn        6.3       portfolio         none我正在努力解决如何转换数据,以便将资产类别名称和金额配对并绑定到投资组合标签(及其直接子项)。如何在结果中配对同级标签?我想要的结果如下所示:type        assets  rateOfReturn    assetClassName  assetAmountportfolio   600000  6.3             Bonds           100000portfolio   600000  6.3             Equities        500000
查看完整描述

3 回答

?
DIEA

TA贡献1820条经验 获得超2个赞

尝试类似的方法:


rows = []

columns = ['assets',  'rateOfReturn',    'assetClassName',  'assetAmount']

for entry in root.xpath('//assetClassDetails'):

    row = []

    row.extend([entry.xpath('preceding-sibling::assets/text()')[0],

                entry.xpath('following-sibling::rateOfReturn/text()')[0],

                entry.xpath('./assetClassName/text()')[0],

                entry.xpath('./assetAmount/text()')[0]])

    rows.append(row)

pd.DataFrame(rows,columns=columns)

输出:


    assets  rateOfReturn    assetClassName  assetAmount

0   600000  6.3     Bonds   100000

1   600000  6.3     Equities    500000

另一种有趣的方法是使用另一个库:


import pandas_read_xml as pdx

df1 = pdx.read_xml(r'path\to\myfile.xml',['portfolio','assetClassDetails'])

df2 = pdx.read_xml(r'path\to\myfile.xml',['portfolio'])

pd.concat([df2[['assets','rateOfReturn']],df1], axis=1)

输出:


assets     rateOfReturn assetClassName  assetAmount

0   600000  6.3         Bonds             100000

1   600000  6.3         Equities        500000


查看完整回答
反对 回复 2023-06-27
?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

使用 @JackFleeting 提到的包的另一种方法可能是:


import pandas_read_xml as pdx

from pandas_read_xml import fully_flatten


df = (pdx.read_xml(r'path\to\myfile.xml', ['portfolio'])

      .pipe(fully_flatten))

展平将列表(XML 中的同级标签)展开为单独的行,或将字典(XML 中的子标签)展开为单独的列。


查看完整回答
反对 回复 2023-06-27
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

下面(不使用任何外部库)


import xml.etree.ElementTree as ET


xml = """

<portfolio>

    <assets>600000</assets>

    <assetClassDetails>

        <assetClassName>Bonds</assetClassName>

        <assetAmount>100000</assetAmount>

    </assetClassDetails>

    <assetClassDetails>

        <assetClassName>Equities</assetClassName>

        <assetAmount>500000</assetAmount>

    </assetClassDetails>

    <rateOfReturn>6.3</rateOfReturn>

</portfolio>

"""

data = []

root = ET.fromstring(xml)

global_properties = {'assets': root.find('assets').text, 'rateOfReturn': root.find('rateOfReturn').text,

                     'type': root.tag}

for asset in root.findall('.//assetClassDetails'):

    entry = {x.tag: x.text for x in list(asset)}

    for k, v in global_properties.items():

        entry[k] = v

    data.append(entry)

for entry in data:

    print(entry)

输出


{'assetClassName': 'Bonds', 'assetAmount': '100000', 'assets': '600000', 'rateOfReturn': '6.3', 'type': 'portfolio'}

{'assetClassName': 'Equities', 'assetAmount': '500000', 'assets': '600000', 'rateOfReturn': '6.3', 'type': 'portfolio'}



查看完整回答
反对 回复 2023-06-27
  • 3 回答
  • 0 关注
  • 193 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信