感谢您对以下方面的帮助:我需要阅读一个大型XML文件并将其转换为CSV格式。
我有两个假设要做同样的函数,只有一个(function1)使用iterparse(因为我需要处理大约2GB文件)而另一个函数没有(函数2)。
Function2对于相同的XML文件(但最多150 MB)非常有效,并且在该大小之后由于内存而失败。
我遇到的问题是,尽管代码(对于function1)没有出错,但它会丢失一些孩子(这是一个很大的问题!)。另一方面,功能2读取所有孩子,并且没有松散的'或任何失败。
问:你能否在function1的代码中看到为什么有些孩子会丢失(或者没有正确阅读或被忽略)?
注1:我需要准备好发送50 KB XML样本。
注2:变量' nchil_count'只计算孩子的数量。
CODE(function1):
def function1 ():
# This function uses Iterparse
# Doesn't give errors but looses some children. Why?
# prints output to csv file, WCEL.csv
from xml.etree.cElementTree import iterparse
fname = "C:\Leonardo\Input data\Xml input data\NetactFiles\Netact_3g_rnc11_t1.xml"
# ELEMENT_LIST = ["WCEL"]
# Delete contents from exit file
open("C:\Leonardo\Input data\Xml input data\WCEL.csv", 'w').close()
# Open exit file
with open("C:\Leonardo\Input data\Xml input data\WCEL.csv", "a") as exit_file:
with open(fname) as xml_doc:
context = iterparse(xml_doc, events=("start", "end"))
context = iter(context)
event, root = context.next()
for event, elem in context:
if event == "start" and elem.tag == "{raml20.xsd}managedObject":
# if event == "start":
if elem.get('class') == 'WCEL':
print elem.attrib
# print elem.tag
element = elem.getchildren()
nchil_count = 0
for child in element:
if child.tag == "{raml20.xsd}p":
nchil_count = nchil_count + 1
# print child.tag
# print child.attrib
val = child.text
# print val
val = str (val)
exit_file.write(val + ",")
exit_file.write('\n')
print nchil_count
elif event == "end" and elem.tag == "{raml20.xsd}managedObject":
# Clear Memory
root.clear()
xml_doc.close()
exit_file.close()
return ()
代码(功能2):
def function2 (xmlFile):
# Using Element Tree
# Successful
# Works well with files of 150 MB, like an XML (RAML) RNC export from Netact (1 RNC only)
# It fails with huge files due to Memory
import xml.etree.cElementTree as etree
import shutil
with open("C:\Leonardo\Input data\Xml input data\WCEL.csv", "a") as exit_file:
# Populate the values per cell:
tree = etree.parse(xmlFile)
for value in tree.getiterator(tag='{raml20.xsd}managedObject'):
if value.get('class') == 'WCEL':
print value.attrib
element = value.getchildren()
nchil_count = 0
for child in element:
if child.tag == "{raml20.xsd}p":
nchil_count = nchil_count + 1
# print child.tag
# print child.attrib
val = child.text
# print val
val = str (val)
exit_file.write(val + ",")
exit_file.write('\n')
print nchil_count
exit_file.close() ## File closing after writing.
return ()
答案 0 :(得分:1)
我有类似的问题。但是有一些重要的区别:
但结果是等价的:一些节点被忽略(丢失)。文件中没有任何内容可以解释原因。对于给定的文件 - 相同的节点。但是,当你只进行技术更改(格式为xmllint) - 其他节点丢失时。
我重新组织了代码(没有xpath(),iterparse没有tag参数,'start'和'end'事件,用element.tag属性值控制进程)并发现 SOMETIMES (我不知道什么时候)过程“忘记”默认的NAMESPACE 。我的意思是,在大多数情况下,element.tag的值是“{namespace uri} tag_name”,但在大约2%的情况下 - 只是“tag_name”。这就是xpath()找不到它们的原因。
我知道文件中的所有内容都来自一个默认命名空间,所以我可以自己添加“{namespace uri}”,并正确处理文件。
如果在主标记中明确声明了名称空间前缀并在所有其他标记中使用,则没有问题。
在解析大型XML文件时,这看起来像是一个错误 - 如果你在xml.etree中有相同的效果,可能不会在lxml中?