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

如何使用Python将大型XML文件数据插入Postgresql表并展示

Python实现大型XML文件批量入库PostgreSQL方案

1. 环境依赖安装

先安装需要的第三方库:
pip install psycopg2-binary lxml

2. 建表语句

首先在PostgreSQL中创建对应字段的表,可根据业务需求调整字段类型:

CREATE TABLE clearing_operations (
    id SERIAL PRIMARY KEY,
    file_id VARCHAR(32) NOT NULL,
    file_type VARCHAR(16) NOT NULL,
    start_date DATE NOT NULL,
    end_date DATE NOT NULL,
    inst_id VARCHAR(16) NOT NULL,
    file_date DATE NOT NULL,
    oper_id VARCHAR(32) NOT NULL UNIQUE,
    oper_type VARCHAR(16) NOT NULL,
    msg_type VARCHAR(16) NOT NULL,
    sttl_type VARCHAR(16) NOT NULL,
    oper_date TIMESTAMP NOT NULL,
    host_date TIMESTAMP NOT NULL,
    oper_amount NUMERIC(18,2) NOT NULL,
    oper_currency VARCHAR(3) NOT NULL,
    request_amount NUMERIC(18,2) NOT NULL,
    request_currency VARCHAR(3) NOT NULL
);

3. 完整实现代码

核心逻辑说明:

  • 采用lxml.iterparse增量解析大型XML,避免全量加载占用过高内存
  • 自动适配XML自带命名空间,无需修改原始XML结构
  • 批量提交数据到PostgreSQL,大幅提升入库效率
import psycopg2
from lxml import etree

# 配置参数
XML_PATH = "替换为你的XML文件实际路径"
DB_CONFIG = {
    "host": "替换为数据库地址",
    "port": 5432,
    "user": "替换为数据库用户名",
    "password": "替换为数据库密码",
    "dbname": "替换为数据库名称"
}
NS = {"sv": "http://bpc.ru/sv/SVXP/clearing"} # 对应示例XML的命名空间
BATCH_SIZE = 1000 # 每1000条提交一次,可根据服务器性能调整

def main():
    # 初始化数据库连接
    conn = psycopg2.connect(**DB_CONFIG)
    cur = conn.cursor()
    insert_sql = """
        INSERT INTO clearing_operations (
            file_id, file_type, start_date, end_date, inst_id, file_date,
            oper_id, oper_type, msg_type, sttl_type, oper_date, host_date,
            oper_amount, oper_currency, request_amount, request_currency
        ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
    """
    batch_data = []
    file_level_fields = {}
    # 增量解析XML
    for event, elem in etree.iterparse(XML_PATH, events=("end",), tag=["{"+NS["sv"]+"}clearing", "{"+NS["sv"]+"}operation"]):
        tag_name = elem.tag.split("}")[-1]
        if tag_name == "clearing":
            # 提取文件级公共字段
            file_level_fields = {
                "file_id": elem.xpath("sv:file_id/text()", namespaces=NS)[0],
                "file_type": elem.xpath("sv:file_type/text()", namespaces=NS)[0],
                "start_date": elem.xpath("sv:start_date/text()", namespaces=NS)[0],
                "end_date": elem.xpath("sv:end_date/text()", namespaces=NS)[0],
                "inst_id": elem.xpath("sv:inst_id/text()", namespaces=NS)[0],
                "file_date": elem.xpath("sv:file_date/text()", namespaces=NS)[0]
            }
        elif tag_name == "operation":
            # 提取单条操作明细字段
            oper_data = {
                "oper_id": elem.xpath("sv:oper_id/text()", namespaces=NS)[0],
                "oper_type": elem.xpath("sv:oper_type/text()", namespaces=NS)[0],
                "msg_type": elem.xpath("sv:msg_type/text()", namespaces=NS)[0],
                "sttl_type": elem.xpath("sv:sttl_type/text()", namespaces=NS)[0],
                "oper_date": elem.xpath("sv:oper_date/text()", namespaces=NS)[0],
                "host_date": elem.xpath("sv:host_date/text()", namespaces=NS)[0],
                "oper_amount": elem.xpath("sv:oper_amount/sv:amount_value/text()", namespaces=NS)[0],
                "oper_currency": elem.xpath("sv:oper_amount/sv:currency/text()", namespaces=NS)[0],
                "request_amount": elem.xpath("sv:oper_request_amount/sv:amount_value/text()", namespaces=NS)[0],
                "request_currency": elem.xpath("sv:oper_request_amount/sv:currency/text()", namespaces=NS)[0]
            }
            # 合并字段生成入库行
            row = (
                file_level_fields["file_id"], file_level_fields["file_type"], file_level_fields["start_date"],
                file_level_fields["end_date"], file_level_fields["inst_id"], file_level_fields["file_date"],
                oper_data["oper_id"], oper_data["oper_type"], oper_data["msg_type"], oper_data["sttl_type"],
                oper_data["oper_date"], oper_data["host_date"], oper_data["oper_amount"], oper_data["oper_currency"],
                oper_data["request_amount"], oper_data["request_currency"]
            )
            batch_data.append(row)
            # 达到批量阈值提交数据
            if len(batch_data) >= BATCH_SIZE:
                cur.executemany(insert_sql, batch_data)
                conn.commit()
                batch_data = []
            # 清理已解析节点释放内存
            elem.clear()
            while elem.getprevious() is not None:
                del elem.getparent()[0]
    # 提交剩余未入库数据
    if batch_data:
        cur.executemany(insert_sql, batch_data)
        conn.commit()
    cur.close()
    conn.close()

if __name__ == "__main__":
    main()

4. 数据查询展示

入库完成后可以直接在PostgreSQL中查询数据,示例查询语句:

-- 查询前10条操作记录
SELECT oper_id, oper_date, oper_amount, oper_currency FROM clearing_operations LIMIT 10;

如果需要用Python展示查询结果,可以新增如下代码:

def show_query_result():
    conn = psycopg2.connect(**DB_CONFIG)
    cur = conn.cursor()
    cur.execute("SELECT oper_id, oper_date, oper_amount, oper_currency FROM clearing_operations LIMIT 10")
    results = cur.fetchall()
    print("操作ID|操作时间|金额|币种")
    print("---|---|---|---")
    for row in results:
        print(f"{row[0]}|{row[1]}|{row[2]}|{row[3]}")
    cur.close()
    conn.close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 15:06:05