-Xercesの構造

Xerces2の構造は実はCoccon2に似ています。Xerces2もCocoon2もどちらも基本はスキャナ-フィルタ-フィルタ-フィルタ...と続くつくりです。スキャナがストリームよりバイト配列を読み出し、テキストパースを行い、イベントを発火します。発火したイベントがフィルタ列の先頭に順次送出され、フィルタのイベントハンドラ内で次のフィルタのハンドラを呼び出していきます。最後にXerces2ではSAXドライバもしくはDOMビルダーにイベントが送られるのです。このスキャナやフィルタといったコンポーネントの組み合わせ・連結は、Configurationでやります。NekoHTMLではHTMLConfigurationです。Cocoon2ではシリアライザと呼ばれる、HTTPレスポンスへコンテンツを書き出す部分でイベントが起こります。
Xerces2ではこのイベントおよびそのハンドラはXNIというAPIセット中のSAXハンドラに似たインターフェイスを経て実装されていますし、Cocoon2はSAXハンドラです。
NekoHTMLはXNIで実装されています。そのコンポーネントの連鎖は、

  • HTMLScanner
  • HTMLTagBalancer
  • XercesのSAXドライバ
  • ユーザー実装SAXハンドラ

となります。SAXドライバのところにDOMビルダーが置き換わる違いなので、Xerces2のSAXパーサーおよびDOMパーサーは動作がまったく同じになります。違いは、イベントハンドラ型であるSAXはパース途中でユーザーコード(SAXハンドラ)でタイミングが取れる一方、DOMビルダーはEOFまでパースして後にはじめて結果を取得するタイミングです。またDOMはそのW3CAPIのために、パース例外が途中で出てしまうと結果(ノード)は一切とれません。PullパーサーはSAXの亜種のようなもので、スキャナのイベント発火を外部イテレータで取るのでよりユーザーコードでタイミングがとれますが、わざわざPullでやるほどのメリットは実装中であまり出せる「機会」がありません。
Kariyushiでは、パイプライン構造を抽象化したConfigurationに、スキャナやコンポーネントダイナミックに組み合わせる機能があります(今日、2年前に書いたコードを最新XNIでマイグレーションしましたのでこの部分は完成しています)。このパイプラインにNekoHTMLのHTMLScannerなどのコンポーネントをセットしていけばいいかなと、今時点では考えています。2年前につくったのは、HTMLリクエストやJDBCドライバ、PalmDBをスキャンして、位置情報(測地系や表記)の変換をフィルタで行った後、Cocoon2のユーザー実装SAXハンドラやXSLTを経てアウトプットするというサーバーです。ゼネコンと電機メーカーに1本ずつ売っただけ(まぁ、べらぼうな値段ですが)で死蔵していたものです。