【问题标题】:XML PARSER -Parsing a large file for a particular format outputXML PARSER - 为特定格式输出解析大文件
【发布时间】:2013-03-29 08:53:24
【问题描述】:

我正在尝试解析 large xml 文件并将标签打印到输出文件。我正在使用 minidom,我的代码对于 30Mb 文件运行良好,但对于较大的文件,它会出现内存错误。所以我使用缓冲读取文件,但现在我无法获得所需的输出。

XML 文件

> <File> <TV>Sony</TV> <FOOD>Burger</FOOD> <PHONE>Apple</PHONE> </File>   
> <File> <TV>Samsung</TV> <FOOD>Pizza</FOOD> <PHONE>HTC</PHONE> </File>  
> <File> <TV>Bravia</TV> <FOOD>Pasta</FOOD> <PHONE>BlackBerry</PHONE> </File>  

期望的输出

索尼、汉堡、苹果
三星、比萨、HTC
Bravia、意大利面、黑莓

当使用缓冲区读取时,它会给我一个输出说:-
索尼、汉堡、苹果
三星、Piz Bravia、意大利面、黑莓

while 1:
    content = File.read(2048)
        if not len(content):
            break
         else:
             for lines in StringIO(content):
                lines = lines.lstrip(' ')
                if lines.startswith("<TV>"):
                   TV =  lines.strip("<TV>")
                   tvVal = TV.split("</TV>")[0]
                   #print tvVal
                   w2.writelines(str(tvVal)+",")
                elif lines.startswith("<FOOD>"):
                   FOOD =  lines.strip("<FOOD>")
                   foodVal = FOOD.split("</FOOD>")[0]
                   #print foodVal
                   w2.writelines(str(foodVal)+",")
                   ............................
                   ...........................

我尝试使用 seek(),但仍然无法获得所需的输出。

【问题讨论】:

    标签: python xml xml-parsing large-files seek


    【解决方案1】:

    您一次读取 2048 个字节,这会将读取光标放在一行的中间。在下一次读取中,该行的其余部分被丢弃,因为它不是以标签开头。

    考虑使用iterparse,而不是滚动您自己的解析器。 lxml 包含更快的 iterparse 版本 这是一个例子

    import cStringIO
    from xml.etree.ElementTree import iterparse
    
    fakefile = cStringIO.StringIO("""<temp>
      <email id="1" Body="abc"/>
      <email id="2" Body="fre"/>
      <email id="998349883487454359203" Body="hi"/>
    </temp>
    """)
    for _, elem in iterparse(fakefile):
        if elem.tag == 'email':
            print elem.attrib['id'], elem.attrib['Body']
        elem.clear()
    

    【讨论】:

    • 正如我已经说过的,我使用了 minidom 解析器,它工作得非常好,但我遇到的唯一问题是在 大型文件 中并阅读它在缓冲区。我应该检查 标签,如果缓冲区给了我最后一行 Pasta;我应该回滚并搜索 。继续使用 seek() 和 tell() 但我很困惑并在这里寻求帮助。
    • Iterparse 设计用于处理大文件,因为您可以使用它来迭代解析文件,丢弃不必要的信息。与minidom 不同,您不必将整个文件保存到内存中
    • import cStringIO from xml.etree.ElementTree import iterparse File = open("File.xml","rb") FRead = File.read() x = cStringIO.StringIO(Fread) for event, elem in iteparse(x): if elem.tag == 'File': print elem.attrib['TV'] elem.clear() 这不起作用:(
    • 在您的示例中,TV 是子元素,而不是属性。并且不要将整个文件读入StringIO,这将违背iterparse 的目的。只需将文件直接传递给iterparse
    【解决方案2】:

    感谢您的支持,我终于编写了我的代码,它在这里工作得很好

    import lxml import etree    
    for event, element in etree.iterparse(the_xml_file):
        if 'TV' in element.tag:
            print element.text
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-05
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 2010-12-09
      • 1970-01-01
      • 2014-01-28
      相关资源
      最近更新 更多