【问题标题】:iterparse elements getting cleared before I can capture the data在我可以捕获数据之前清除 iterparse 元素
【发布时间】:2019-01-04 05:01:48
【问题描述】:

我正在尝试使用 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>

这是行为不端代码的 sn-p:

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() 会擦除文本,即使看起来应该先打印?有什么建议吗?

【问题讨论】:

    标签: python python-3.x celementtree iterparse


    【解决方案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)
    

    在您的原始示例中,当遇到 &lt;/entity&gt; 结束标记时,所有子元素都已被清除(之前遇到过它们的结束标记)。

    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)
    

    【讨论】:

      【解决方案2】:

      我会这样做,我也不确定你想对数据做什么 所以我只是按照你的原样打印它:

      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')}
      

      【讨论】:

      • 你能用 iterparse 和 elem.clear() 来完成这项工作吗?我没有内存先将整个文件放入内存。谢谢。
      猜你喜欢
      • 2016-11-08
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多