2

我有一个大的 xml 文件(大约 84MB),格式如下:

<books>
    <book>...</book>
    ....
    <book>...</book>
</books>

我的目标是提取每一本书并获得它的属性。我试图解析它(就像我对其他 xml 文件所做的那样),如下所示:

from xml.dom.minidom import parse, parseString

fd = "myfile.xml"
parser = parse(fd)
## other python code here

但代码似乎在解析指令中失败。为什么会发生这种情况,我该如何解决?

我应该指出,该文件可能包含希腊语、西班牙语和阿拉伯语字符。

这是我在 ipython 中得到的输出:

In [2]: fd = "myfile.xml"

In [3]: parser = parse(fd)
Killed

我想指出计算机在执行过程中冻结,所以这可能与内存消耗有关,如下所述。

4

3 回答 3

7

尝试使用更易于使用的lxml 。

#!/usr/bin/env python
from lxml import etree

with open("myfile.xml") as fp:
    tree = etree.parse(fp)
    root = tree.getroot()

    print root.tag

    for book in root:
        print book.text
于 2012-12-29T13:09:02.580 回答
6

我强烈建议在这里使用 SAX 解析器。我不建议minidom在任何大于几兆字节的 XML 文档上使用。我已经看到它使用大约 400MB 的 RAM 读取大小约为 10MB 的 XML 文档。我怀疑您遇到的问题是由minidom请求过多的内存引起的。

Python 带有一个 XML SAX 解析器。要使用它,请执行以下操作。

from xml.sax.handlers import ContentHandler
from xml.sax import parse

class MyContentHandler(ContentHandler):
    # override various ContentHandler methods as needed...


handler = MyContentHandler()
parse("mydata.xml", handler)

您的ContentHandler子类将覆盖ContentHandler中的各种方法(例如startElementstartElementNS、或。这些处理由 SAX 解析器在读取您的 XML 文档时生成的事件endElementendElementNScharacters

SAX 是一种比 DOM 更“低级”的 XML 处理方式。除了从文档中提取相关数据外,您的 ContentHandler 还需要跟踪它当前包含的元素。然而,从好的方面来说,由于 SAX 解析器不会将整个文档保存在内存中,它们可以处理任何大小的 XML 文档,包括那些比您的更大的文档。

我没有尝试在这种大小的 XML 文档上使用其他 DOM 解析器,例如 lxml,但我怀疑 lxml 仍然需要相当长的时间并使用大量内存来解析您的 XML 文档。如果每次运行代码时都必须等待它读取 84MB XML 文档,这可能会减慢您的开发速度。

最后,我不相信你提到的希腊语、西班牙语和阿拉伯语字符会引起问题。

于 2012-12-29T13:49:59.683 回答
3

有 2 种 XML 解析器(这适用于任何语言)。

  1. DOM 解析(这是您正在使用的)。在这种类型中,整个 XML 文件被读入内存结构,然后通过方法访问。

  2. SAX 解析。这是一种解析算法,它以逐步方式读取每段 XML。这种技术可以让您更好地检测和处理错误。

一般来说,DOM 比 SAX 更容易,因为很多细节都由它的本地方法处理。

SAX 更具挑战性,因为您必须编写 SAX 解析“运行”在 XML 文档遍历期间的方法。

于 2012-12-29T13:03:48.653 回答