我正在尝试使用Python使用cElementTree和iterparse解析大型XML文件(27GB)。我能够提取所有标签,但是由于某种原因,没有检索到任何元素文本(它始终显示为“无”)。我检查了文档和StackOverflow,但无济于事。我尝试使用lxml作为最后的手段进行解析,并且它可以工作,但是如果可能的话,我希望在cElementree上进行解析。 更新:当我注释掉elem.clear()行时,它显示了正在解析的数据,但是现在我试图弄清楚为什么clear()方法在打印数据之前先清除数据(最终我想放数据分成单独的数据结构(如数据库)。我假设我需要清除数据,以便在文件解析期间不占用最大内存。这是“ Python中的一切都是对象”的情况之一吗?
使用从文件中提取的较小样本,我仍然遇到相同的错误。 XML文件看起来像这样(尽管有更多条目):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><entityList><entity
xmlns:ns2="urn:hl7-org:v3" xmlns:ns3="urn:axolotl-com:pdo">
<fragmentId>d68e616e-a6bc-4630-b104-3891859a8ce4</fragmentId>
<aggregateId>H1060734453</aggregateId>
<source>b6167864-5f74-40e5-97c5-7e551a3a4a7d</source>
<sourceName>SHM ADT</sourceName>
<sourceOid>2.16.840.1.113883.3.2.2.3.1.21.3</sourceOid>
<sourceAaoid>2.16.840.1.113883.3.62.2</sourceAaoid>
</entity></entityList>
以下是行为不当的代码段:
import xml.etree.ElementTree as etree
xml=r'C:\sample.xml'
count = 0
for event, elem in etree.iterparse(xml):
if event == 'end':
if elem.tag == 'entity':
count+=1
for child in elem:
print (child.tag, child.attrib, child.text)
elem.clear()
print(count)
我要
fragmentId {} None
aggregateId {} None
source {} None
sourceName {} None
sourceOid {} None
sourceAaoid {} None
即使看起来应该首先进行打印,为什么elem.clear()也会擦除文本?有什么建议吗?
答案 0 :(得分:1)
这就是我要怎么做,我也不知道你想对数据做什么 所以我只是按原样打印它:
import xml.etree.ElementTree as ET
tree = ET.parse(path_to_xml)
root = tree.getroot()
def tree_parser(root):
for child in root.getchildren():
if not child.getchildren():
print(child.tag, child.text)
else:
tree_parser(child)
tree_parser(root)
fragmentId d68e616e-a6bc-4630-b104-3891859a8ce4
aggregateId H1060734453
source b6167864-5f74-40e5-97c5-7e551a3a4a7d
sourceName SHM ADT
sourceOid 2.16.840.1.113883.3.2.2.3.1.21.3
sourceAaoid 2.16.840.1.113883.3.62.2
根据您的评论:
def tree_parser(root, seen=set()):
for child in root.getchildren():
if not child.getchildren():
data = (child.tag, child.text)
seen.add(data)
else:
tree_parser(child, seen)
return seen
for _, element in etree.iterparse(path_to_xml):
c = tree_parser(element)
print(c)
{('aggregateId', 'H1060734453'),
('fragmentId', 'd68e616e-a6bc-4630-b104-3891859a8ce4'),
('source', 'b6167864-5f74-40e5-97c5-7e551a3a4a7d'),
('sourceAaoid', '2.16.840.1.113883.3.62.2'),
('sourceName', 'SHM ADT'),
('sourceOid', '2.16.840.1.113883.3.2.2.3.1.21.3')}
答案 1 :(得分:1)
将elem.clear()
移动到if elem.tag == 'entity':
语句下的块中是有效的。这样可以确保仅在处理完子元素后才清除它们。
count = 0
for event, elem in etree.iterparse(xml):
if event == 'end':
if elem.tag == 'entity':
count+=1
for child in elem:
print (child.tag, child.attrib, child.text)
elem.clear() # Clear only if </entity> is encountered
print(count)
在您的原始示例中,到遇到</entity>
结束标记时,所有子元素均已清除(它们的结束标记较早地出现)。
count = 0
for event, elem in etree.iterparse(xml):
if event == 'end':
if elem.tag == 'entity':
count+=1
for child in elem:
print (child.tag, child.attrib, child.text)
elem.clear() # Clears fragmentId ... sourceAaoid before </entity>
print(count)