我尝试使用Python来清理一些凌乱的XML文件,它做了三件事:
我在使用BeautifulSoup
时这样做了,但是,由于我的一些XML文件超过1GB,我遇到了内存问题。相反,我研究了一些像xml.sax
这样的流方法,但我没有完全接受这种方法。那么有人可以给我一些建议吗?
xml_str = """
<DATA>
<ROW>
<assmtid>1</assmtid>
<Year>1988</Year>
</ROW>
<ROW>
<assmtid>2</assmtid>
<Year>NULL</Year>
</ROW>
<ROW>
<assmtid>2</assmtid>
<Year>1990</Year>
</ROW>
</DATA>
"""
xml_str_update = re.sub(r">NULL", ">", xml_str)
soup = BeautifulSoup(xml_str_update, "lxml")
print soup.data.prettify().encode('utf-8').strip()
经过一些测试并从Jarrod Roberson那里得到建议后,下面是一个可能的解决方案。
import os
import xml.etree.cElementTree as etree
from cStringIO import StringIO
def getelements(xml_str):
context = iter(etree.iterparse(StringIO(xml_str), events=('start', 'end')))
event, root = next(context)
for event, elem in context:
if event == 'end' and elem.tag == "ROW":
elem.tag = elem.tag.lower()
elem.text = "\n\t\t"
elem.tail = "\n\t"
for child in elem:
child.tag = child.tag.lower()
if child.text == "NULL":
# if do not like self-closing tag,
# add ​, which is a zero width space
child.text = ""
if child.text == None:
child.text = ""
# print event, elem.tag
yield elem
root.clear()
with open(pth_to_output_xml, 'wb') as file:
# start root
file.write('<data>\n\t')
for page in getelements(xml_str):
file.write(etree.tostring(page, encoding='utf-8'))
# close root
file.write('</data>')
答案 0 :(得分:1)
当不希望构建内存中的树时 实际上,使用不依赖的迭代解析技术 读取整个源文件。 lxml提供两种方法:供应 目标解析器类使用iterparse方法
import xml.etree.ElementTree as etree
for event, elem in etree.iterparse(xmL, events=('start', 'end', 'start-ns', 'end-ns')):
print event, elem
以下是关于如何执行此操作的very complete tutorial。
这将一次解析XML文件并将其提供给您 每一步都是如此。当标签第一时,start将触发 遇到。此时elem将为空,除了elem.attrib 包含标签的属性。结束时会触发 遇到了结束标记,并且已经读取了中间的所有内容。
然后在您的事件处理程序中,您只需在遇到转换后的信息时写出。