在Python中通过xml.etree.ElementTree生成的XML文件中插入换行符
我在Python中使用xml.etree.ElementTree创建了一个xml文件。然后我用
tree.write(filename, "UTF-8")
把这个文档写到一个文件里。
但是当我用文本编辑器打开这个文件时,发现标签之间没有换行,所有内容都在一行里。
我该怎么做才能把文档写成“美观的格式”,这样在所有的xml标签之间就会有换行(希望还能有缩进等)呢?
6 个回答
ElementTree 并不支持漂亮打印(即格式化输出),但你可以使用其他的 XML 模块来实现。
比如说,你可以用 xml.dom.minidom.Node.toprettyxml()
这个方法:
Node.toprettyxml([indent=""[, newl=""[, encoding=""]]])
这个方法会返回一个格式化好的文档版本。这里的
indent
是用来设置缩进的字符串,默认是一个制表符;newl
是每行末尾输出的字符串,默认是换行符 \n。
你可以根据自己的需要来使用 indent
和 newl
。
下面是一个使用默认格式化字符的例子:
>>> from xml.dom import minidom
>>> from xml.etree import ElementTree
>>> tree1=ElementTree.XML('<tips><tip>1</tip><tip>2</tip></tips>')
>>> ElementTree.tostring(tree1)
'<tips><tip>1</tip><tip>2</tip></tips>'
>>> print minidom.parseString(ElementTree.tostring(tree1)).toprettyxml()
<?xml version="1.0" ?>
<tips>
<tip>
1
</tip>
<tip>
2
</tip>
</tips>
>>>
更新 2022 - Python 3.9 及更高版本
在 Python 3.9 及以后的版本中,标准库里新增了一个功能叫做 xml.etree.ElementTree.indent:
示例:
import xml.etree.ElementTree as ET
root = ET.fromstring("<fruits><fruit>banana</fruit><fruit>apple</fruit></fruits>""")
tree = ET.ElementTree(root)
ET.indent(tree, ' ')
# writing xml
tree.write("example.xml", encoding="utf-8", xml_declaration=True)
感谢 Michał Krzywański 提供这个更新!
在 Python 3.9 之前
我发现了一种新方法,可以避免使用新的库和重新解析 XML。你只需要把你的根元素传给这个函数(下面会解释):
def indent(elem, level=0):
i = "\n" + level*" "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
indent(elem, level+1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
在 xml.etree.ElementTree.Element 实例上,有一个叫做 "tail" 的属性。这个属性可以在一个节点后面设置一个字符串:
"<a>text</a>tail"
我找到了一篇2004年的链接,讲述了一个 元素库函数,它使用这个 "tail" 属性来缩进一个元素。
示例:
root = ET.fromstring("<fruits><fruit>banana</fruit><fruit>apple</fruit></fruits>""")
tree = ET.ElementTree(root)
indent(root)
# writing xml
tree.write("example.xml", encoding="utf-8", xml_declaration=True)
在 "example.xml" 中的结果:
<?xml version='1.0' encoding='utf-8'?>
<fruits>
<fruit>banana</fruit>
<fruit>apple</fruit>
</fruits>
我觉得最简单的解决办法是换用 lxml 这个库。在大多数情况下,你只需要把你的导入语句从 import xml.etree.ElementTree as etree
改成 from lxml import etree
或者类似的写法就可以了。
然后你可以在序列化的时候使用 pretty_print
选项:
tree.write(filename, pretty_print=True)
(这个选项在 etree.tostring
上也可以用)