【发布时间】:2017-07-08 14:12:32
【问题描述】:
我正在尝试使用 SAX 解析器从以下示例 xml 文档(原始文档大约 30 GB)中删除所有 project1 节点(以及它们的子元素)。它将是可以有一个单独的修改文件,或者可以使用内联编辑。
sample.xml
<ROOT>
<test src="http://dfs.com">Hi</test>
<project1>This is old data<foo></foo></project1>
<bar>
<project1>ty</project1>
<foo></foo>
</bar>
</ROOT>
这是我的尝试..
parser.py
from xml.sax.handler import ContentHandler
import xml.sax
class MyHandler(xml.sax.handler.ContentHandler):
def __init__(self, out_file):
self._charBuffer = []
self._result = []
self._out = open(out_file, 'w')
def _createElement(self, name, attrs):
attributes = attrs.items()
if attributes:
out = ''
for key, value in attributes:
out += ' {}={}'.format(key, value)
return '<{}{}>'.format(name, out)
return '<{}>'.format(name)
def _getCharacterData(self):
data = ''.join(self._charBuffer).strip()
self._charBuffer = []
self._out.write(data.strip()) #remove strip() if whitespace is important
def parse(self, f):
xml.sax.parse(f, self)
def characters(self, data):
self._charBuffer.append(data)
def startElement(self, name, attrs):
if not name == 'project1':
self._result.append({})
self._out.write(self._createElement(name, attrs))
def endElement(self, name):
if not name == 'project1': self._result[-1][name] = self._getCharacterData()
MyHandler('out.xml').parse("sample.xml")
我无法让它工作。
【问题讨论】:
-
将数据作为文本处理有什么问题?很简单:检查flag,是不是down,抢线,是project1,升flag,写/不写,重复……只是一个策略大纲
-
但是这种方法会导致将整个文件加载到内存中。
-
我的意思是:读取行-处理行-更新状态-决定是否写入。不要一次处理整个文件。没有必要。
-
你甚至可以使用缓冲区来减少写入次数。例如,仅每 1000 行刷新一次缓冲区。如果重要,请自行衡量。
-
@ar7max:将 XML 作为文本处理的问题是众所周知的——当 XML 发生完全合理的变化时,它会导致脆弱的解决方案以多种方式中断。请不要提出这样的建议。谢谢。