Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Python清理大型XML文件(流解析)_Python_Xml - Fatal编程技术网

用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

我尝试使用Python清理一些凌乱的XML文件,这有三件事:

  • 将40%-50%的标记名从大写转换为小写
  • 删除标记之间的NULL
  • 删除标记之间的空行
  • 我在使用
    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 &#x200B;, 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