我希望将一个巨大的 XML 文件分割成较小的部分。我想扫描文件以查找特定标签,然后获取 和 之间的所有信息,然后将其保存到文件中,然后继续浏览文件的其余部分。
我的问题是试图找到一种干净的方法来记录标签的开始和结束,以便我可以在使用“for line in f”扫描文件时抓取其中的文本
我不想使用哨兵变量。有没有一种Python式的方法来完成这个任务?
文件太大,无法读入内存。
处理 XML 数据有两种常见方法。
其中一个称为 DOM,它代表文档对象模型。这种 XML 解析风格可能是您在查看文档时看到的,因为它将整个 XML 读取到内存中以创建对象模型。
第二种称为SAX,它是一种流式方法。解析器开始读取 XML 并向您的代码发送有关某些事件的信号,例如当找到新的开始标签时。
所以 SAX 显然是您所需要的。 Sax 解析器可以在 python 库中的 xml.sax 和 xml.parsers.expat 下找到。
我已经成功使用 cElementTree.iterparse 方法来完成类似的任务。
我有一个大型 xml 文档,其中包含带有标签“resFrame”的重复“条目”,我想过滤掉特定 id 的条目。这是我使用的代码:
源文档具有以下结构
<snapDoc>
<bucket>....</bucket>
<bucket>....</bucket>
<bucket>....</bucket>
...
<resFrame><id>234234</id>.....</resFrame>
<frame><id>344234</id>.....</frame>
<resFrame>...</resFrame>
<frame>...</frame>
</snapDoc>
我使用以下脚本创建了一个较小的文档,该文档具有相同的结构、存储桶条目,并且只有具有特定 id 的 resFrame 条目。
#!/usr/bin/env python2.6
import xml.etree.cElementTree as cElementTree
start = '''<?xml version="1.0" encoding="UTF-8"?>
<snapDoc>'''
def main():
print start
context = cElementTree.iterparse('snap.xml', events=("start", "end"))
context = iter(context)
event, root = context.next() # get the root element of the XML doc
for event, elem in context:
if event == "end":
if elem.tag == 'bucket': # i want to write out all <bucket> entries
elem.tail = None
print cElementTree.tostring( elem )
if elem.tag == 'resFrame':
if elem.find("id").text == ":4:39644:482:-1:1": # i only want to write out resFrame entries with this id
elem.tail = None
print cElementTree.tostring( elem )
if elem.tag in ['bucket', 'frame', 'resFrame']:
root.clear() # when done parsing a section clear the tree to safe memory
print "</snapDoc>"
main()
对于这种情况,您可以考虑使用 ElementTree iterparse 函数。
多么偶然啊! Will Larson 刚刚发表了一篇关于 Handling Very Large CSV and XML File in Python.
的好文章。主要的收获似乎是使用
xml.sax
模块,正如 Van 提到的,并创建一些宏函数来抽象低级 SAX API 的细节。
这是一篇古老但非常好的文章,来自 Uche Ogbuji 也非常好的 Python & XMl 专栏。它涵盖了您的确切问题,并使用标准库的 sax 模块,就像其他答案所建议的那样。 分解、处理、重组