REXML で大きな XML ファイルを処理したらあまりにも遅かった。Ruby で書かれているのでいたし方ないんですが。もちろん REXML は標準でついているし、手軽に使えて良いという大きなメリットがあるけど、行う処理が数時間レベルなので速くしたい。そこで Libxml http://libxml.rubyforge.org/ を試すことに。
行うのは XML → XML 変換なので、エンティティの出力が気になった。そこで次のようなコードを実行して、結果を比較してみる。

テストしたコード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/env ruby
#
require 'rubygems'
require 'xml/libxml'
require 'rexml/document'
str =<<EOS
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>Tosshi&apos;s メモ書き</title>
<array>
<item attr='&apos;'> &lt;html&gt; &apos;TAG&quot; </item>
<item attr="&quot;"><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item>
</array>
</root>
EOS
puts <<EOS
\[ libxml-ruby \]
EOS
xp = XML::Parser.new
xp.string = str
libxmldoc = xp.parse
puts "document :"
puts libxmldoc
node = libxmldoc.root.find_first("title")
print "Node :"
puts node
print "content :"
puts node.content
print "child.to_s:"
puts node.child.to_s
libxmldoc.root.find("array/item").each do |item|
print "Node :"
puts item
print "content :"
puts item.content
print "child.to_s:"
puts item.child.to_s
end
puts <<EOS
\[ REXML \]
EOS
rexmldoc = REXML::Document.new(str)
puts "Document :"
puts rexmldoc
el = rexmldoc.root.elements\["title"\]
print "Element :"
puts el
print "text :"
puts el.text
print "get_text :"
puts el.get_text
rexmldoc.root.elements.each("array/item") do |item|
print "Element :"
puts item
print "text :"
puts item.text
print "get_text :"
puts item.get_text
end

結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ ruby testxml.rb
\[ libxml-ruby \]
Document :
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>Tosshi's メモ書き</title>
<array>
<item attr="'"> &lt;html&gt; 'TAG" </item>
<item attr="&quot;"><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item>
</array>
</root>
Node :<title>Tosshi's メモ書き</title>
content :Tosshi's メモ書き
child.to_s:Tosshi's メモ書き
Node :<item attr="'"> &lt;html&gt; 'TAG" </item>
content : <html> 'TAG"
child.to_s: &lt;html&gt; 'TAG"
Node :<item attr="&quot;"><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item>
content : CDATA &lt;html&gt; &apos;TAG&qout; <>"'
child.to_s:<!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]>
\[ REXML \]
Document :
<?xml version='1.0' encoding='UTF-8'?>
<root>
<title>Tosshi&apos;s メモ書き</title>
<array>
<item attr='&apos;'> &lt;html&gt; &apos;TAG&quot; </item>
<item attr='&quot;'><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item>
</array>
</root>
Element :<title>Tosshi&apos;s メモ書き</title>
text :Tosshi's メモ書き
get_text :Tosshi&apos;s メモ書き
Element :<item attr='&apos;'> &lt;html&gt; &apos;TAG&quot; </item>
text : <html> 'TAG"
get_text : &lt;html&gt; &apos;TAG&quot;
Element :<item attr='&quot;'><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item>
text : CDATA &lt;html&gt; &apos;TAG&qout; <>"'
get_text : CDATA &lt;html&gt; &apos;TAG&qout; <>"'