python - 如何以 xml 节点的有序方式序列化 python ElementTree?

标签 python xml serialization xml-parsing elementtree

我有一个内存中的 python XML ElementTree,它看起来像

<A>
  <B>..</B>
  <C>..</C>
  <D>..</D>
</A>

我通过

将ElementTree序列化为xml
xmlstr = minidom.parseString(ET.tostring(root)).toprettyxml("  ")

每次我调用上面的 tostring() 方法时,内部节点 B、C、D 的顺序都会改变。我如何才能确保我的序列化遵循确定的顺序?

最佳答案

我意识到这里的许多答案都暗示了这一点,但是

minidom.parseString(ET.tostring(root)).toprettyxml("  ")

实际上是一种 pretty-print XML 文件的非常糟糕的方式。

它涉及解析、使用 ET 序列化,然后再次解析并使用完全不同的 XML 库再次序列化。这是愚蠢和浪费的,如果 minidom 搞砸了我也不会感到惊讶。

如果安装了它,切换到 lxml and use its built-in pretty-printing function .

如果您出于某种原因坚持使用 xml.etree.ElementTree,您可以使用简单的递归函数就地美化树:

# xmlhelpers.py

# taken from http://effbot.org/zone/element-lib.htm#prettyprint
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

用法很简单:

import xml.etree.ElementTree as ET
from xmlhelpers import indent    

root = ET.fromstring("<A><B>..</B><C>..</C><D>..</D></A>")
indent(root)

print( ET.tostring(root) )

这打印了一个很好的缩进版本:

b'<A>\n  <B>..</B>\n  <C>..</C>\n  <D>..</D>\n</A>\n'

也就是说,永远不要使用“tostring”将 XML 树写入文件。

始终使用 XML 库提供的函数编写 XML 文件。

tree = ET.ElementTree(root) # only necessary if you don't already have a tree
tree.write(filename, encoding="UTF-8")

关于python - 如何以 xml 节点的有序方式序列化 python ElementTree?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46010406/

相关文章:

python - 计算字符串中的字母数字和标点符号

python - FastAPI 应用程序在本地运行但不在 Docker 容器中

c# - 使用 Linq to XML 和数组创建 XML

xml - XML 属性值中的控制字符

binary - 如何分析二进制文件?

python - Apache Beam 每用户 session 窗口未合并

python - Pandas:以 pythonic 方式拆分字符串

java - 如何使用 XmlPullParser 解析 XML

javascript - 解析 javascript 函数中的外部范围引用以进行序列化

java - 使用内部类进行子类化,仅序列化外部类