如何解决ElementTree追加XML元素后格式缩进不正确的问题?
哈哈,这个坑我踩过!ElementTree默认对手动追加的元素不会自动处理缩进,导致输出的XML结构乱糟糟的。别担心,分两种情况给你解决办法:
方案一:Python 3.9+ 用官方自带的indent()函数
从Python 3.9开始,xml.etree.ElementTree新增了专门的indent()方法,一键搞定缩进,用法超简单:
import xml.etree.ElementTree as ET # 解析原有XML内容 root = ET.fromstring('''<data> <country name="Liechtenstein"> <rank>1</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> </country> </data>''') # 解析并追加新元素 new_tag = ET.fromstring(''' <usertype id="99999"> <role name="admin" /> </usertype>''') root.append(new_tag) # 关键步骤:调用indent设置缩进 ET.indent(root, space=" ", level=0) # 输出格式化后的XML(或者写入文件) print(ET.tostring(root, encoding='unicode')) # 写入文件的话用下面这句 # ET.ElementTree(root).write('formatted.xml', encoding='utf-8', xml_declaration=True)
space:指定缩进用的空格数(比如用" "就是4个空格缩进)level:起始缩进层级,一般设0就好
方案二:自定义缩进函数(适配Python 3.8及以下版本)
如果你的Python版本还没到3.9,那就自己写个递归函数,给每个元素的text和tail属性添加换行与缩进空格,实现格式化效果:
import xml.etree.ElementTree as ET def indent(elem, level=0): # 定义每个层级的缩进空格 indent_space = " " i = "\n" + level * indent_space if len(elem): # 处理有子元素的节点 if not elem.text or not elem.text.strip(): elem.text = i + indent_space if not elem.tail or not elem.tail.strip(): elem.tail = i # 递归处理子元素 for child in elem: indent(child, level + 1) # 修正最后一个子元素的尾部缩进 if not child.tail or not child.tail.strip(): child.tail = i else: # 处理空元素 if level and (not elem.tail or not elem.tail.strip()): elem.tail = i # 解析原有XML root = ET.fromstring('''<data> <country name="Liechtenstein"> <rank>1</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> </country> </data>''') # 追加新元素 new_tag = ET.fromstring(''' <usertype id="99999"> <role name="admin" /> </usertype>''') root.append(new_tag) # 调用自定义缩进函数 indent(root) # 输出结果 print(ET.tostring(root, encoding='unicode'))
这个函数的核心逻辑是递归遍历所有元素,通过调整元素的text(元素内容前的文本)和tail(元素结束后的文本)来插入换行和缩进,让XML结构层级分明。
另外提个小细节:如果用write()方法保存文件,记得加上encoding='utf-8'和xml_declaration=True参数,避免编码问题;要是想把空元素从<neighbor ... />改成<neighbor ...></neighbor>,可以给write()加个short_empty_elements=False参数。
内容的提问来源于stack exchange,提问作者shinzou
相关产品推荐
相关产品推荐

