DOMでXML@Python,PHP5

PHPPythonもDOMでXMLを扱うためのモジュールはあるのだが、整形する際にできる空白のせいでこちらの思ったとおりのXMLファイルを出力しない。また、空白が入っているXMLファイルを読み込む際の扱いも違うのでメモしておく。

PHP5における空白の扱い

PHP5ではDOM XMLで読み込むときに、preserveWhiteSpaceの値を設定することで余計な空白を取り除いてくれる。しかし、これは混合ノードにおける空白に対してのみでテキストノードだけの場合は消してくれない。以下のようなコードでXMLファイルに対して処理した結果について考えてみよう。

<?php
$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->load('sample.xml')
$dom->save('sample.xml')
?>

このとき、以下のsample.xmlから[A]の部分の空白は取り除いてくれるが、[B]の部分の空白は取り除いてくれない。

<?xml version='1.0' encoding='utf-8'?>
<Root>
                    ・・・[A]
    <Record>
        <item>
                    ・・・[B]
            なのは
        </item>
    </Record>
                    ・・・[A]
</Root>

出力結果は以下のようになる。

<?xml version='1.0' encoding='utf-8'?>
<Root>
    <Record>
        <item>
            
            なのは
        </item>
    </Record>
</Root>

また、書き出すときはformatOutputの値によってノードの階層によって空白を入れてくれるのだが、すでに一部に空白が入っている状態だと整形されているものと受け取るのか、なにもせずにそのまま出力される。そのため、書き出す前に自分で必要のない空白はすべて削除する必要がある。実は他のパラメータでうまくいくのかもしれないが。

Pythonにおける空白の扱い

Pythonではxml.dom.minidomで読み込むときに自動的に空白を削除する方法が備わっていないので、値を取り出すときにstrip()を使う必要がある。書き込む際にはwritexml()で書き出すためのフォーマットを指定できるのだが、これがまたこちらの思い通りには動いてくれない。以下のようなコードでXMLファイルに対して処理した結果について考えてみる。

# -*- coding: sjis -*-
from xml.dom.minidom import parse

dom = parse('sample.xml')
file = open('sample.xml','w')
dom.writexml(file,'','\t','\n')
file.close()

以下のようなsample.xmlを処理すると

<?xml version='1.0' encoding='utf-8'?>
<Root><Record>フェイト</Record></Root>

1回実行した結果は以下の通りできれいに整形されてファイルが出力される。

<?xml version='1.0' encoding='utf-8'?>
<Root>
    <Record>
        フェイト
    </Record>
</Root>

同じコードでさらに実行すると空白が無駄に増えている。

<?xml version='1.0' encoding='utf-8'?>
<Root>
    
    
    <Record>
        
        フェイト
    
    </Record>
    

</Root>

空白が入ると余計にファイル容量が大きくなってしまうのでこれは避けたい。そのため、ファイルを読み込んでparseするときに空白のテキストノードは削除してしまうほうがよいだろう。整形をwritexmlに頼らないで自分で書くのもありだが、結局読み込む際には空白が邪魔になってしまうので毎回はじめに取り除いてしまったほうが楽だろう。


こちらももっと楽に扱える方法があるのかもしれない。