循环遍历大型XML文件

时间:2011-02-14 17:32:49

标签: xml coldfusion

我遇到了大约20-30 MB(650000行)的XML文件循环问题。

这是我的元代码:

<cffile action="READ" ile="file.xml" variable="usersRaw">

<cfset usersXML = XmlParse(usersRaw)>
<cfset advsXML = XmlSearch(usersXML, "/advs/advuser")>
<cfset users = XmlSearch(usersXML, "/advs/advuser/user")>

<cfset numUsers = ArrayLen(users)>
<cfloop index="i" from="1" to="#numUsers#">
    ... some selects...
    ... insert...
    <cfset advs = annunciXml[i]["vehicle"]>
    <cfset numAdvs = ArrayLen(advs)> 
    <cfloop index="k" from="1" to="#numAdvs#">        
        ... insert... or ... update...
    </cfloop>
</cfloop>

xml文件的结构是(是的,不是很好: - )

<advs>
   <advuser>
      <user>
      </user>
      <vehicle>
      <vehicle>
   </advuser>
</advs>

在大约120,000行后,我收到一个错误:“内存不足”。

如何改善脚本的性能?

如何诊断最大内存消耗量?

4 个答案:

答案 0 :(得分:10)

@SamG是正确的,因为DOM解析器不能执行ColdFusion XML解析,但是SAX很痛苦,而是使用StAX解析器,它提供了一个更简单的迭代器接口。 See the answer to another question I provided for an example of how to do this with ColdFusion

这大致就是你为你的例子做的事情:

<cfset fis = createObject("java", "java.io.FileInputStream").init(
    "#getDirectoryFromPath(getCurrentTemplatePath())#/file.xml"
)>
<cfset bis = createObject("java", "java.io.BufferedInputStream").init(fis)>
<cfset XMLInputFactory = createObject("java", "javax.xml.stream.XMLInputFactory").newInstance()>
<cfset reader = XMLInputFactory.createXMLStreamReader(bis)>

<cfloop condition="#reader.hasNext()#">
    <cfset event = reader.next()>
    <cfif event EQ reader.START_ELEMENT>
        <cfswitch expression="#reader.getLocalName()#">
            <cfcase value="advs">
                <!--- root node, do nothing --->
            </cfcase>
            <cfcase value="advuser">
                <!--- set values used later on for inserts, selects, updates --->
            </cfcase>
            <cfcase value="user">
                <!--- some selects and insert --->
            </cfcase>
            <cfcase value="vehicle">
                <!--- insert or update --->
            </cfcase>
        </cfswitch>
    </cfif>
</cfloop>

<cfset reader.close()>

答案 1 :(得分:2)

orangepips提供了合理的解决方案。请查看Ben Nadel在ColdFusion中处理非常大的XML文件的解决方案。我已经在一个包含120万行的50MB XML文件上测试了他的方法。 Ben使用类似于orangepips在这里提供的方法 - 使用Java流式传输,然后使用XMLParse ColdFusion中的每个节点来获取货物。看看它 - 就像Ben Nadel的大部分代码和教程一样,它只是有效。

http://www.bennadel.com/blog/1345-Ask-Ben-Parsing-Very-Large-XML-Documents-In-ColdFusion.htm

答案 2 :(得分:1)

我认为Cold Fusion XML Parser使用DOM Parsing,它不适合这种文件大小。您应该尝试找到一个事件驱动的SAX解析器。也许这个链接会有所帮助 http://coldfusion.sys-con.com/node/236002

答案 3 :(得分:1)

我不知道ColdFusion,但20-30Mb并不超出构建内存树的技术范围;许多人经常在200Mb文件上运行XSLT转换。

转向SAX解析听起来像一个极端的措施 - 它是一个如此低级别的界面。