最直接可靠的方式是使用lxml库的getparent()方法;标准库xml.etree.ElementTree需手动维护父关系,如递归传参或iterparse栈模拟,不推荐动态打补丁。

在Python中遍历XML并同时获取父节点信息,最直接可靠的方式是使用 lxml 库的 getparent() 方法——标准库 xml.etree.ElementTree 默认不保存父引用,需手动维护或改用 lxml。
用 lxml 一键获取父节点
lxml 的 Element 对象原生支持 .getparent(),无需额外配置:
- 安装:
pip install lxml - 解析后任意节点调用
node.getparent()即可返回其父元素(根节点返回None) - 支持 XPath、迭代、修改等完整功能,性能优于标准库
示例:
from lxml import etree xml_str = "text " root = etree.fromstring(xml_str) for elem in root.iter(): parent = elem.getparent() print(f"标签: {elem.tag}, 父标签: {parent.tag if parent is not None else 'None'}")
用 xml.etree.ElementTree 手动构建父关系
如果必须用标准库,可通过递归遍历时显式传递父节点:
立即学习“Python免费学习笔记(深入)”;
- 不依赖外部包,适合轻量或受限环境
- 遍历时把当前节点作为参数传给子节点处理函数
- 避免后期反复查找父节点,逻辑清晰可控
示例:
import xml.etree.ElementTree as ET
def walk_with_parent(elem, parent=None):
print(f"当前: {elem.tag}, 父节点: {parent.tag if parent is not None else 'None'}")
for child in elem:
walk_with_parent(child, elem)
root = ET.fromstring(" ")
walk_with_parent(root)
用 iterparse 遍历时缓存父栈(适合大文件)
处理超大 XML 时,iterparse 可边解析边处理,用栈模拟父子层级:
- 遇到
start事件时将当前元素压栈,此时栈顶下一个是其父节点 - 遇到
end事件时弹出,保持栈与实际嵌套深度一致 - 内存友好,适合 GB 级 XML 流式处理
示例关键逻辑:
stack = []
for event, elem in ET.iterparse("file.xml", events=("start", "end")):
if event == "start":
if stack:
parent = stack[-1]
print(f"{elem.tag} 的父节点是 {parent.tag}")
stack.append(elem)
elif event == "end":
stack.pop()
不推荐:给 ElementTree 打补丁加 parent 属性
有人尝试通过 elem.parent = parent 动态赋值来“修复”标准库,但存在风险:
- 新创建的子元素(如用
SubElement)不会自动设 parent - 复制、深拷贝、XPath 查找结果等场景 parent 关系易丢失
- 代码可维护性差,容易引发隐性 bug
除非有强约束不能引入第三方库,否则优先选 lxml 或递归传参方式。










