我即将构建一个需要构建 XML 文档并将其发布到 Web 服务的项目的一部分,并且我想用 Python 来完成它,作为扩展我在其中的技能的一种手段。
不幸的是,虽然我非常了解 .NET 中的 XML 模型,但我不确定 Python 中的 XML 模型的优缺点是什么。
有人有在 Python 中进行 XML 处理的经验吗?你建议我从哪里开始?我将要构建的 XML 文件将相当简单。
就我个人而言,我在一个 XML 繁重的项目中使用了几个内置选项,并决定将pulldom作为不太复杂的文档的最佳选择。
特别是对于简单的小东西,我喜欢事件驱动的解析理论,而不是为一个相对简单的结构设置一大堆回调。 这是关于如何使用 API 的一个很好的快速讨论。
我喜欢的是:您可以在for
循环中处理解析,而不是使用回调。您还会延迟完整解析(“拉”部分),并且仅在调用expandNode()
. 这在不牺牲易用性和简单性的情况下满足了我对“负责任”效率的一般要求。
ElementTree有一个不错的 pythony API。我认为它甚至作为 python 2.5 的一部分提供
它是在纯 python 中,正如我所说,非常好,但如果你最终需要更高的性能,那么lxml会公开相同的 API 并在后台使用 libxml2。理论上,您可以在发现需要时将其换掉。
通常有 3 种主要的处理 XML 的方法:dom、sax 和 xpath。如果您有能力一次将整个 xml 文件加载到内存中,并且您不介意处理数据结构,并且您正在查看大部分/大部分模型,则 dom 模型很好。如果您只关心几个标签,并且/或者您正在处理大文件并且可以按顺序处理它们,那么 sax 模型非常棒。xpath 模型各有一点——您可以选择所需数据元素的路径,但它需要使用更多库。
如果你想直接使用 Python 打包,minidom 是你的答案,但它很蹩脚,文档是“这里是 dom 上的文档,去弄清楚”。这真的很烦人。
就个人而言,我喜欢 cElementTree,它是 ElementTree 的一个更快(基于 c 的)实现,它是一个类似 dom 的模型。
我使用过 sax 系统,在很多方面它们的感觉更像是“pythonic”,但我通常最终会创建基于状态的系统来处理它们,而这就是疯狂(和错误)。
如果你喜欢研究,我说使用 minidom,如果你想要运行良好的好代码,我会说使用 ElementTree。
我已经在几个项目中使用过 ElementTree 并推荐它。
它是 Python 的,随 Python 2.5 一起提供,包括 c 版本的 cElementTree (xml.etree.cElementTree),它比纯 Python 版本快 20 倍,并且非常易于使用。
lxml 具有一些性能优势,但它们并不均衡,您应该首先针对您的用例检查基准。
据我了解,ElementTree 代码可以很容易地移植到 lxml。
这在一定程度上取决于文档需要有多复杂。
我在编写 XML 时经常使用 minidom,但通常只是读取文档,进行一些简单的转换,然后将它们写回。直到我需要对元素属性进行排序的能力(以满足不能正确解析 XML 的古老应用程序)之前,这已经足够好用了。那时我放弃了,自己编写了 XML。
如果您只处理简单的文档,那么自己动手会比学习框架更快、更简单。如果您可以想象手动编写 XML,那么您也可以手动编写它(只需记住正确转义特殊字符,并使用str.encode(codec, errors="xmlcharrefreplace")
)。除了这些混乱之外,XML 足够规则,以至于您不需要特殊的库来编写它。如果文档太复杂而无法手动编写,那么您可能应该查看已经提到的框架之一。在任何时候都不需要编写通用的 XML 编写器。
您也可以尝试untangle来解析简单的 XML 文档。
由于您提到您将构建“相当简单”的 XML,minidom 模块(Python 标准库的一部分)可能会满足您的需要。如果您对 XML 的 DOM 表示有任何经验,您应该会发现该 API 非常简单。
我编写了一个接收 XML 请求并创建 XML 响应的 SOAP 服务器。(不幸的是,这不是我的项目,所以它是封闭源代码,但这是另一个问题)。
对我来说,如果您有一个“适合”模式的数据结构,那么创建 (SOAP) XML 文档是相当简单的。
我保留信封,因为响应信封(几乎)与请求信封相同。然后,由于我的数据结构是一个(可能是嵌套的)字典,我创建了一个字符串,将该字典转换为 <key>value</key> 项。
这是递归简化的任务,我最终得到了正确的结构。这一切都是在 python 代码中完成的,目前对于生产使用来说已经足够快了。
您也可以(相对)轻松地构建列表,尽管取决于您的客户,除非您给出长度提示,否则您可能会遇到问题。
对我来说,这要简单得多,因为字典比一些自定义类更容易工作。对于书籍而言,生成 XML 比解析要容易得多!
Python 带有 ElementTree 内置库,但 lxml 在速度和功能(模式验证、sax 解析、XPath、各种迭代器和许多其他特性)方面对其进行了扩展。
您必须安装它,但在许多地方,它已经被假定为标准设备的一部分(例如,Google AppEngine 不允许基于 C 的 Python 包,但对 lxml、pyyaml 和其他少数几个例外)。
您的问题是关于构建 XML 文档。
使用lxml有很多方法,我花了一段时间才找到一个,它似乎易于使用且易于阅读。
来自lxml doc 中关于使用 E-factory 的示例代码(略微简化):
E-factory 为生成 XML 和 HTML 提供了一种简单而紧凑的语法:
>>> from lxml.builder import E
>>> html = page = (
... E.html( # create an Element called "html"
... E.head(
... E.title("This is a sample document")
... ),
... E.body(
... E.h1("Hello!"),
... E.p("This is a paragraph with ", E.b("bold"), " text in it!"),
... E.p("This is another paragraph, with a", "\n ",
... E.a("link", href="http://www.python.org"), "."),
... E.p("Here are some reserved characters: <spam&egg>."),
... )
... )
... )
>>> print(etree.tostring(page, pretty_print=True))
<html>
<head>
<title>This is a sample document</title>
</head>
<body>
<h1>Hello!</h1>
<p>This is a paragraph with <b>bold</b> text in it!</p>
<p>This is another paragraph, with a
<a href="http://www.python.org">link</a>.</p>
<p>Here are some reserved characters: <spam&egg>.</p>
</body>
</html>
我很欣赏 E-factory 它遵循的东西
可读性很重要。
支持以下内容:
例如:
from lxml import etree
from lxml.builder import E
lst = ["alfa", "beta", "gama"]
xml = E.root(*[E.record(itm) for itm in lst])
etree.tostring(xml, pretty_print=True)
导致:
<root>
<record>alfa</record>
<record>beta</record>
<record>gama</record>
</root>
我强烈推荐阅读 lxml 教程——它写得很好,会给你更多使用这个强大库的理由。
lxml 唯一的缺点是它必须被编译。有关如何在几分之一秒内从 wheel 格式包安装 lxml的更多提示,请参阅SO answer。
我强烈推荐SAX - Simple API for XML
- 在 Python 库中实现。正如之前的海报所讨论的,它们相当容易通过 evendriven 设置和处理XML
,API
并且与验证DOM
样式XML
解析器不同,内存占用量低。
我假设 .NET 处理 XML 的方式建立在某个版本的 MSXML 之上,在这种情况下,我假设使用例如 minidom 会让您有宾至如归的感觉。但是,如果您正在进行简单的处理,任何库都可能会这样做。
在 Python 中处理 XML 时,我也更喜欢使用 ElementTree,因为它是一个非常简洁的库。
如果您要构建 SOAP 消息,请查看soaplib。它在底层使用 ElementTree,但它为序列化和反序列化消息提供了更简洁的接口。