使用xml.dom.minidom中的parseString解析XML文件的效率很低?

时间:2015-02-10 16:51:29

标签: python xml performance minidom

我正在尝试使用Python 2.7解析XML文件。 XML文件的大小为370 + MB,包含6,541,000行。

XML文件由以下300K块组成:

<Tag:Member>
    <fileID id = '123456789'>
    <miscTag> 123 </miscTag>
    <miscTag2> 456 </miscTag2>
    <DateTag> 2008-02-02 </DateTag>
    <Tag2:descriptiveTerm>Keyword_1</Tag2:descriptiveTerm>
    <miscTag3>6.330016</miscTag3>
    <historyTag>
        <DateTag>2001-04-16</DateTag>
        <reasonTag>Refresh</reasonTag>
    </historyTag>
    <Tag3:make>Keyword_2</Tag3:make>
    <miscTag4>
            <miscTag5>
                <Tag4:coordinates>6.090,6.000 5.490,4.300 6.090,6.000 </Tag4:coordinates>
            </miscTag5>
        </miscTag4>
</Tag:Member>

我使用了以下代码:

from xml.dom.minidom import parseString

def XMLParser(filePath):    
    """ ===== Load XML File into Memory ===== """
    datafile = open(filePath)
    data = datafile.read()
    datafile.close()
    dom = parseString(data)    

    length = len(dom.getElementsByTagName("Tag:Member"))


    counter = 0
    while counter < length:
        """ ===== Extract Descriptive Term ===== """
        contentString = dom.getElementsByTagName("Tag2:descriptiveTerm")[counter].toxml()

        laterpart = contentString.split("Tag2:descriptiveTerm>", 1)[1]

        descriptiveTerm = laterpart.split("</Tag2:descriptiveTerm>", 1)[0]    


        if descriptiveGroup == "Keyword_1":
            """ ===== Extract Make ===== """
            contentString = dom.getElementsByTagName("Tag3:make")[counter].toxml()

            laterpart = contentString.split("<Tag3:make>", 1)[1]

            make = laterpart.split("</Tag3:make>", 1)[0]



            if descriptiveTerm == "Keyword_1" and make == "Keyword_2":
                """ ===== Extract ID ===== """        
                contentString = dom.getElementsByTagName("Tag:Member")[counter].toxml()

                laterpart = contentString.split("id=\"", 1)[1]

                laterpart = laterpart.split("Tag", 1)[1]

                IDString = laterpart.split("\">", 1)[0]



                """ ===== Extract Coordinates ===== """
                contentString = dom.getElementsByTagName("Tag:Member")[counter].toxml()

                laterpart = contentString.split("coordinates>", 1)[1]

                coordString = laterpart.split(" </Tag4:coordinates>", 1)[0]            


        counter += 1

所以,我已经运行了这个,并发现它需要大约27GB的内存,并且解析上述每个块的时间超过20秒。所以解析这个文件需要2个月!

我想我写了一些效率低下的代码。谁能帮我改进呢?

非常感谢。

1 个答案:

答案 0 :(得分:1)

对于这种大小的文件,正确的方法是流解析器(SAX风格,而不是DOM风格,因此minidom完全不合适)。有关使用lxml.iterparse(一种使用libxml2的最新/现代流式解析器 - 一种快速高效的用C语言编写的XML解析库 - 在其后端)的说明,请参阅this answer,以节省内存的方式或the article on which that answer is based

一般情况下 - 当您看到与成员关联的元素时,您应该在内存中构建该成员,并且当您看到与标记结尾相关联的事件时,您将发出或处理内置的内容 - 记忆内容,并开始一个全新的。