Python の何が気に入っているのかというはなし 〜SAX の場合〜
端的に言うとライブラリの「センス」がいいのです。細かい気配りの効いたお店ってあるでしょう。あんな感じ。
今日ちょっと話したんですが、最近大変気に入った Python の SAX のはなし。たいていの OO 言語の SAX 実装は Visitor パターンで、startElement や endElement などのメンバをもったオブジェクトと XML の実データを渡してパースしてやることになると思います。Python の場合 ContentHandler クラスの子クラスを作ることになります。ここまではふつう。
ふと、saxutils パッケージに XMLGenerator クラスなる、ContentHandler のサブクラスがあります。説明を読むと、そのまま出力されるだけだったり、クラス名も最初謎でした。これ何に使うんだ? ここで気づくのです! あぁ、これまさに Generator じゃん!!
from xml.sax.saxutils import XMLGenerator gen = XMLGenerator() gen.startDocument() gen.startElement('html', {}) gen.startElement('head', {}) gen.endElement('head') gen.startElement('body', {}) gen.startElement('a', {'href': 'http://d.hatena.ne.jp/u-no/'}) gen.characters('>>diary<<') gen.endElement('a') gen.endElement('body') gen.endElement('html') gen.endDocument()
わかりますか? startElement などの、本来 Parser ライブラリから呼ばれるメンバ関数を、ユーザーのプログラムから呼ぶんです。出力はこんな感じ。
<?xml version="1.0" encoding="iso-8859-1"?> <html><head></head><body><a href="http://d.hatena.ne.jp/u-no/">>>diary<<</a></body></html>
私はこのとき、DOM ツリーを作らずに、XML エスケープをしながら出力する XMLWriter クラスのようなモノを探していました。それがまさか Parser のパッケージにあるとは! Parser 用インターフェースを逆に使うと Generator になるよという指摘。1本とられた感じです。
さらに関心したのは、startElement の第2引数。SAX からは Attributes なるクラスのオブジェクトがとんでくるらしいんですが、よく見てください。辞書型とインターフェースが酷似している。そして、XMLGenerator 内では辞書型と共通のメンバ関数しか使ってないようで、そのため上記のように第2引数に辞書型を渡せるんですね。明らかに上記のような使い方を意識しています。
ライブラリの善し悪しって、どういう使われ方をするか想定できるかに依ると思うのですよ。この例なんかは本当に気配りがきいていて、Python ではこういう「上品な」仕組みによく出くわします。そこがいいんですね。
# そういえば、これでさらに閉じタグとの対応を validate してくれれば良かったんだけどな。まぁ、ラッパーでも作ればいいんですけど