用Python清理大型XML文件(流解析)
我尝试使用Python清理一些凌乱的XML文件,这有三件事:用Python清理大型XML文件(流解析),python,xml,Python,Xml,我尝试使用Python清理一些凌乱的XML文件,这有三件事: 将40%-50%的标记名从大写转换为小写 删除标记之间的NULL 删除标记之间的空行 我在使用BeautifulSoup时做到了这一点,但是,我遇到了内存问题,因为我的一些XML文件超过1GB。相反,我研究了一些流方法,如xml.sax,但我没有完全了解这种方法。有人能给我一些建议吗 xml_str = """ <DATA> <ROW> <assmtid>1</ass
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()
xml_str=”“”
1.
1988
2.
无效的
2.
1990
"""
xml\u str\u update=re.sub(r>NULL“,“>”,xml\u str)
soup=BeautifulSoup(xml\u str\u更新,“lxml”)
打印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>')
导入操作系统
将xml.etree.cElementTree作为etree导入
从cStringIO导入StringIO
def getelements(xml_str):
context=iter(etree.iterparse(StringIO(xml_str),events=('start','end'))
事件,根=下一个(上下文)
对于事件,上下文中的元素:
如果event='end'和elem.tag==“ROW”:
elem.tag=elem.tag.lower()
elem.text=“\n\t\t”
elem.tail=“\n\t”
对于elem中的儿童:
child.tag=child.tag.lower()
如果child.text==“NULL”:
#如果不喜欢自动关闭标签,
#添加;,这是一个零宽度的空间
child.text=“”
如果child.text==无:
child.text=“”
#打印事件,elem.tag
屈服线
root.clear()
以open(pth_to_output_xml,'wb')作为文件:
#起始根
file.write('\n\t')
对于getelements(xml_str)中的页面:
file.write(etree.tostring(第页,编码='utf-8'))
#近根
file.write(“”)
迭代解析
当不需要或不需要构建内存中的树时
实际上,使用一种不依赖于
读取整个源文件。lxml提供了两种方法:提供
使用iterparse方法的目标解析器类
下面是一个关于如何做到这一点的例子
这将一次分块解析XML文件,并在
这条路的每一步。当标记第一次出现时,将触发start
遇到。此时,除elem.attrib之外,elem将为空
包含标记属性的。当
遇到结束标记,其间的所有内容都已读取
然后在事件处理程序中,您只需写出遇到的转换信息。@alecxe-感谢您的建议。是否需要明确列出其案例需要转换的标签?可能重复感谢回复。然而,在我的例子中,我还需要输出整个XML文件。你有什么建议吗?这里是最新的问题:我的答案的最后一行告诉你你需要做什么,就像副本中的答案一样。
import xml.etree.ElementTree as etree
for event, elem in etree.iterparse(xmL, events=('start', 'end', 'start-ns', 'end-ns')):
print event, elem