You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python ElementTree解析大XML提取关联数据效率优化咨询

问题背景与需求

我有一个约100MB的XML文件,包含大量与“instrument”相关的数据点,其中重点关注“loan_contract”数据。文件中约有5000个instrument,XML结构示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<security_master v="47">
    <header>
        <type>initialize</type>
        <timestamp>2023-02-08T02:15:12Z</timestamp>
    </header>
    <payload>
        <instrument id="469408967">
            <master_information>
                <instrument_master>
                </instrument_master>
                <market_master>
                </market_master>
                <organization_master id="321942681">
                </organization_master>
            </master_information>
            <global_information>
            </global_information>
            <debt>
                <fixed_income>
                </fixed_income>
                <bank_loan_details>
                    <amounts>
                    </amounts>
                    <facility>
                    </facility>
                    <loan_contract id="476860356">
                    </loan_contract>
                </bank_loan_details>
            </debt>
        </instrument>
    </payload>
</security_master>

核心需求

为每个instrument提取所有关联的loan_contract元素,最终生成CSV文件,得到一份包含loan_contract及其关联instrument的唯一列表,忽略无loan_contract的instrument。

注意事项

  • 并非所有instrument都关联loan_contract元素(无关联时该标签缺失),部分instrument关联1个,部分关联多个(最大数量未知);
  • loan_contract是instrument的曾孙元素;
  • loan_contract和instrument的格式分别为<loan_contract id="___">和<instrument id="___">。

原低效代码

以下代码可实现需求,但运行效率极低:

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

#parse XML file 

tree = ET.parse('/Users/psteward/Documents/py/py/initial.xml')

root = tree.getroot()

#initialize the list for each field 

INSTRUMENT = []
LOAN_CONTRACT_ID = []

for item in root.findall('payload/instrument/debt/bank_loan_details/loan_contract'):
    LOAN_CONTRACT_ID.append(item.get('id'))

for contract in LOAN_CONTRACT_ID:
    INSTRUMENT.append(root.find('payload/instrument/debt/bank_loan_details/loan_contract[@id="%s"]/../../..' % contract).get('id'))

# set up dataframe with the lists 

instruments_df = pd.DataFrame( 
    list(
        zip(
            INSTRUMENT,
            LOAN_CONTRACT_ID
        )
    ),  
    columns =
    ['INSTRUMENT',
    'LOAN_CONTRACT_ID']
)

instruments_df.to_csv("data.csv")

优化建议

1. 层级遍历优化:正向遍历避免反向查找

原代码先收集所有loan_contract,再逐个反向查找对应的instrument,相当于对每个contract重新遍历一次XML,时间复杂度为O(N*M)(N为contract数量,M为instrument数量),效率极低。

改为直接遍历每个instrument节点,在当前节点内查找关联的loan_contract,一次遍历完成数据收集:

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

tree = ET.parse('/Users/psteward/Documents/py/py/initial.xml')
root = tree.getroot()

data = []
# 遍历所有instrument节点
for instrument in root.findall('payload/instrument'):
    instrument_id = instrument.get('id')
    # 在当前instrument下查找所有loan_contract
    contracts = instrument.findall('debt/bank_loan_details/loan_contract')
    for contract in contracts:
        contract_id = contract.get('id')
        data.append([instrument_id, contract_id])

# 生成DataFrame并保存
instruments_df = pd.DataFrame(data, columns=['INSTRUMENT', 'LOAN_CONTRACT_ID'])
instruments_df.to_csv("data.csv", index=False)

2. 迭代解析优化内存(可选)

如果XML文件后续进一步增大,使用ET.iterparse()进行迭代解析,无需加载整个文件到内存,能进一步提升内存效率:

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

data = []
current_instrument_id = None

# 迭代解析XML,只关注instrument和loan_contract节点
for event, elem in ET.iterparse('/Users/psteward/Documents/py/py/initial.xml', events=('start', 'end')):
    if event == 'start' and elem.tag == 'instrument':
        current_instrument_id = elem.get('id')
    elif event == 'end' and elem.tag == 'loan_contract':
        if current_instrument_id is not None:
            contract_id = elem.get('id')
            data.append([current_instrument_id, contract_id])
    # 清理已处理的节点,释放内存
    elem.clear()

instruments_df = pd.DataFrame(data, columns=['INSTRUMENT', 'LOAN_CONTRACT_ID'])
instruments_df.to_csv("data.csv", index=False)

3. 细节优化

  • 避免使用两个独立列表再zip,直接用二维列表存储数据,减少内存操作;
  • 保存CSV时添加index=False,避免生成多余的索引列。

内容的提问来源于stack exchange,提问作者pdsmth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 15:48:31