XML表拆分需先解析层级与重复性,以等可重复节点为主表,子节点按语义归主表或从表;嵌套结构暗示一对多关系,应拆为orders和order_items;用xml.etree.ElementTree分层提取,注意.text为空字符串、属性用.get()、空值与类型需清洗转换;批量插入用executemany()或CSV导入,并严格控制外键依赖顺序与事务回滚。

XML结构决定表拆分逻辑
不能直接“映射”,必须先解析XML的层级和重复性。重点看 、 这类可重复容器节点,它们通常对应主表;其子节点如 、 则按语义归入主表或外键关联的从表。嵌套深的结构(比如 )天然暗示一对多关系,应拆成 orders 和 order_items 两张表。
用Python + xml.etree.ElementTree做分层提取
避免用正则或字符串切割——XML有命名空间、属性、混合内容等边界情况。xml.etree.ElementTree 足够轻量且标准库自带。关键操作是:对每个顶层重复节点调用 .findall(),再用 .findtext() 提取字段,遇到子集合时递归遍历。注意:.text 可能为 None,需显式判断;属性值用 .get('attr_name') 获取,别硬写 attrib['attr_name'] 否则报 KeyError。
import xml.etree.ElementTree as ETtree = ET.parse('data.xml') root = tree.getroot()
for order_elem in root.findall('order'): order_data = { 'id': order_elem.findtext('id') or '', 'customer_id': order_elem.findtext('customer/id') or '' }
插入 orders 表
insert_order(order_data) # 提取 order_items for item_elem in order_elem.findall('items/item'): item_data = { 'order_id': order_data['id'], 'sku': item_elem.findtext('sku') or '', 'qty': int(item_elem.findtext('quantity') or '0') } insert_order_item(item_data)字段类型与空值处理不匹配会批量失败
数据库列定义(如
INT、NOT NULL)和XML实际内容常不一致。常见坑:的.text是空字符串而非None;在数值列里直接插入会报错;带单位的值如active 需正则清洗。建议统一用函数做转换:2.5kg
-
safe_int(s):返回int(s.strip('kg').strip())或0 -
trim_or_none(s):返回s.strip() if s and s.strip() else None - 所有
INSERT语句用参数化(如cursor.execute("INSERT ...", tuple(vals))),别拼字符串
性能瓶颈在逐行INSERT,不是XML解析
解析10MB XML可能只要200ms,但执行1万次单条 INSERT 可能要8秒。解决方式只有两个:executemany() 批量提交,或生成临时CSV再用数据库原生命令导入(如 PostgreSQL 的 COPY、MySQL 的 LOAD DATA INFILE)。注意:executemany() 的参数列表不能超过数据库驱动限制(MySQLdb 默认1000条),需手动切片;CSV方式要求XML字段严格无换行、无引号嵌套,否则导入会错位。
真正难的是嵌套层级里的外键依赖顺序——必须先插 customers,再插 orders,最后插 order_items,中间任何一步失败,整个事务得回滚。别指望靠数据库级级联搞定,XML本身没事务概念。










