我想使用Clojure从Wiktionary XML转储中提取标题。使用data.zip解析Clojure中的XML时发生OutOfMemoryError
我使用head -n10000 > out-10000.xml
来创建较小版本的原始怪物文件。然后,我用文本编辑器修剪它,使其成为有效的XML。
(def data-9764 "data/wiktionary-en-9764.xml") ; 354K
(def data-99224 "data/wiktionary-en-99224.xml") ; 4.1M
(def data-995066 "data/wiktionary-en-995066.xml") ; 34M
(def data-7999931 "data/wiktionary-en-7999931.xml") ; 222M
下面是XML结构的概述:
<mediawiki>
<page>
<title>dictionary</title>
<revision>
<id>20100608</id>
<parentid>20056528</parentid>
<timestamp>2013-04-06T01:14:29Z</timestamp>
<text xml:space="preserve">
...
</text>
</revision>
</page>
</mediawiki>
这里是我试过的基础上,this answer to 'Clojure XML Parsing'我根据内部行(wc -l
)数重命名的文件:
(ns example.core
(:use [clojure.data.zip.xml :only (attr text xml->)])
(:require [clojure.xml :as xml]
[clojure.zip :as zip]))
(defn titles
"Extract titles from +filename+"
[filename]
(let [xml (xml/parse filename)
zipped (zip/xml-zip xml)]
(xml-> zipped :page :title text)))
(count (titles data-9764))
; 38
(count (titles data-99224))
; 779
(count (titles data-995066))
; 5172
(count (titles data-7999931))
; OutOfMemoryError Java heap space java.util.Arrays.copyOfRange (Arrays.java:3209)
我在做我的代码错了吗?或者,这可能是我正在使用的库中的一个错误或限制?基于REPL实验,似乎我使用的代码是懒惰的。在下面,Clojure使用SAX XML解析器,因此单独应该不是问题。
参见:
更新二零一三年四月三十零日:
我想从Clojure的IRC频道分享一些讨论。我在下面粘贴了一个修改后的版本。 (我删除了用户名,但如果你想贷款,只是让我知道,我会编辑,并给你一个链接)
整个标签在
xml/parse
一次读入内存, 没过多久你甚至打电话给伯爵。而clojure.xml
使用〜懒惰的SAX 解析器来产生一个渴望的具体集合。懒洋洋地处理XML 需要比你想象的多得多的工作 - 并且它会工作你 这样做,而不是一些神奇的clojure.xml
可以为你做。通过致电(count (xml/parse data-whatever))
随时反驳 。
总之,即使使用zip/xml-zip
之前,这xml/parse
会导致一个足够大的文件的OutOfMemoryError
:
(count (xml/parse filename))
目前,我正在探索其他的XML处理选项。在我的列表顶部是clojure.data.xml,如https://stackoverflow.com/a/9946054/109618所述。
啊,是啊。应该早点发现。你一定要'clojure.data.xml'而不是'clojure.xml' - 过渡应该是很容易的。 – Alex 2013-04-30 15:57:38