Python如何复制XML指定子元素及所有后代节点并修改节点名称
解决方案
lxml的Element对象底层基于C结构体实现,Python内置的deepcopy无法正确克隆其节点绑定关系,直接使用etree自带的深拷贝方法即可实现需求,操作放在write_xml调用前执行即可:
核心代码
# 1. 深拷贝elem1的全部节点、属性、子元素 elem1_copy = etree.deepcopy(elem1) # 2. 修改新节点的标签名 elem1_copy.tag = "element_2" # 3. 将新节点追加到head的子节点列表中,位置和element_1同级 head.append(elem1_copy)
完整修改后的代码逻辑
parser = etree.XMLParser(remove_blank_text=True) tree = etree.parse(input_filename, parser) root = tree.getroot() #### 命名空间清理逻辑保留 for elem in root.getiterator(): if not hasattr(elem.tag, 'find'): continue i = elem.tag.find('}') if i >= 0: elem.tag = elem.tag[i+1:] objectify.deannotate(root, cleanup_namespaces=True) def write_xml(file, element): xmlstr = minidom.parseString(ET.tostring(element)).toprettyxml(indent=" ") with open(file, "w") as f: f.write(xmlstr) head = SubElement(root, 'head') # 构建原始element_1节点及所有子元素 elem1 = SubElement(head, 'element_1') elem1.set('xx', xx) sub1 = SubElement(elem1, 'sub1') sub1.set('xxx', "yyy") for key, value in data.items(): sub11 = SubElement(sub1, 'sub1.1') sub11.set('nnn', str(key)) # 其余子元素构建逻辑保留 elem2 = SubElement(elem1, 'elem2') # 其余构建逻辑保留 # ========== 新增克隆逻辑开始 ========== elem1_copy = etree.deepcopy(elem1) elem1_copy.tag = "element_2" head.append(elem1_copy) # ========== 新增克隆逻辑结束 ========== write_xml(output_filename,root)
注意事项
- 如果你使用的是Python标准库的
xml.etree.ElementTree而非lxml,将克隆代码替换为内置deepcopy即可:
from copy import deepcopy elem1_copy = deepcopy(elem1) elem1_copy.tag = "element_2" head.append(elem1_copy)
- 不要直接赋值
new_elem = elem1,该操作仅生成引用,修改任意一个节点都会同步影响另一个 - 克隆后的节点必须显式添加到父节点下,才会被写入最终的XML文件
内容的提问来源于stack exchange,提问作者dominant
相关产品推荐
相关产品推荐

