それはともかく(ってなにが?)、本日はErlangのXML処理。xmerlっていうXML処理系があるんですが、どうもイマイチ。
チュートリアルの冒頭に次のように書いてあります。
- 外部実体はローカルファイルしか読めない。
- ユニコード・サポートは不完全。
1番目はたいして気にならないし、実体管理系(entity manager)がちゃんと分離された作りになっているなら、機能追加も困難ではないはず。
2番目はおもしろくない! 名前はアスキー文字だけ。まー、文字データはutf-8が許されるようなので使えなくはありませんが。(Erlang自体が文字処理/テキスト処理が苦手なので、ユニコードのサポートは辛いでしょうね。)
で使ってみると、いきなり変な挙動。次のような文書を読ませます。
xmerlってば文書要素(document element)の外側は全部無視しちゃう。コメントを読み飛ばすのはまーいいとしましょう。しかし、PIはアプリケーションに渡すべきもので、パーザーがつぶしてしまうのは望ましくないですね。コメントもPIも読み飛ばす仕様かと思ったらそうではなくて、次の例では、PIノード相当のデータを生成しています。
<?xml version="1.0" ?>
<!-- comment 1 -->
<?pi-1 pi conent?>
<?pi-2 pi conent?>
<root />
<?pi-3 pi conent?>
<!-- comment 2 -->
<!-- comment 3 -->
<?xml version="1.0" ?>
<root >
<!-- comment inside element 1 -->
<?pi-inside-element-1 pi conent?>
<?pi-inside-element-2 pi conent?>
<!-- comment inside element 2 -->
</root>
xmerlのヘッダ(インクルードファイル)を読んでいたら、Michael Remondという人に指摘されてxmlDocumentを追加したみたい。どうも文書ノード(document node)の存在を忘れていたようです。構文仕様では、documentの定義は次のようです。
[1] document ::= prolog element Misc*
[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
[27] Misc ::= Comment | PI | S
XML宣言を除いた部分は、Misc* (doctypedecl Misc*)? element Misc*
となり、この正規表現にマッチする列(sequence, list)を子ノード(child nodes)として格納する入れ物としても文書ノードは必要です(他に、文書メタ情報を保持するかもしれません)。xmlDocument(文書ノード相当のデータ構造)の定義だけは追加してますが、実装まで出来てないらしく、パーザーは文書要素を返してきます。文書要素の外側を返すつもりらしい付加情報もあるんですが、空っぽ。そもそも、要素ノードじゃなくて文書ノード返さないとダメだよな。
# 割とマジメに名前空間を扱おうとしているあたりは好感を持ちました。