読者です 読者をやめる 読者になる 読者になる

XMLのDOMツリーから余分な空白を削除する(追記:実際は圧縮)

REXML Tutorial - Homeにあったので、試してみた。(CentOS5.2のRuby 1.8.5のパッケージ付属のrexml)

require 'rexml/document'
include REXML
doc = REXML::Document.new( $stdin, { :compress_whitespace => :all})
doc.write

これで、行頭とかに空白を含むXML文書(上記tutorialにあるサンプルを食わせたところ、行の頭の空白一文字だけはのこった。

$ cat サンプル文書
<inventory title="OmniCorp Store #45x10^3">
  <section name="health">
    <item upc="123456789" stock="12">
      <name>Invisibility Cream</name>
      <price>14.50</price>
      <description>Makes you invisible</description>
    </item>
    <item upc="445322344" stock="18">
      <name>Levitation Salve</name>
      <price>23.99</price>
      <description>Levitate yourself for up to 3 hours per application</description>
    </item>
  </section>
  <section name="food">
    <item upc="485672034" stock="653">
      <name>Blork and Freen Instameal</name>
      <price>4.95</price>
      <description>A tasty meal in a tablet; just add water</description>
    </item>
    <item upc="132957764" stock="44">
      <name>Grob winglets</name>
      <price>3.56</price>
      <description>Tender winglets of Grob. Just add water</description>
    </item>
  </section>
</inventory>
$ cat サンプル文書 | ruby スクリプト
<inventory title='OmniCorp Store #45x10^3'>
 <section name='health'>
 <item stock='12' upc='123456789'>
 <name>Invisibility Cream</name>
 <price>14.50</price>
 <description>Makes you invisible</description>
 </item>
 <item stock='18' upc='445322344'>
 <name>Levitation Salve</name>
 <price>23.99</price>
 <description>Levitate yourself for up to 3 hours per application</description>
 </item>
 </section>
 <section name='food'>
 <item stock='653' upc='485672034'>
 <name>Blork and Freen Instameal</name>
 <price>4.95</price>
 <description>A tasty meal in a tablet; just add water</description>
 </item>
 <item stock='44' upc='132957764'>
 <name>Grob winglets</name>
 <price>3.56</price>
 <description>Tender winglets of Grob. Just add water</description>
 </item>
 </section>
</inventory>

これ、Ruby 1.8.7だと挙動違うかなぁ。
(追記:あーそーか、削除じゃなくてcompressだね。俺って馬鹿すぎ)

追記:いくつかのドキュメントで試してみた

W3C XHTML2 Working Group Home Page(60045バイト)を処理したところ、58728バイトになりました。
他に、preタグの中に空白を入れてみたところ、これも圧縮されてしまいます。これは困った。圧縮対象のタグをいちいち指定してやらないとダメだと判明。そりゃそうですな。
(追記:いちいち指定しなくても、preタグだけ残すのなら、respect_whitespaceという指定をすればいいらしい。

require 'rexml/document'
include REXML
doc = REXML::Document.new( $stdin, { :respect_whitespace => %w{pre}})
doc.write