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

xhtml->sxml

Lisp 系言語で xml を扱うときは sxml 形式に一旦変換することがある。 Gauche にも sxml 関連のライブラリがある。 xml から sxml へ変換する手続きは ssax:xml->sxml だ。 細かいことを考えずに xml を与えるだけでいい。

しかし、ふと xhtml を対象にして変換をかけようとしたときにエラーになってしまった。 この手続きは DTD は読まないので知らない実体参照にぶつかったためだ。

必要な実体参照定義を返す関数を DOCTYPE ハンドラにして ssax:make-parser でパーサを作るというのがまともな解決なのだが、面倒なので無理矢理に実体参照の情報を注入する方法を考えた。

(use sxml.ssax)

(define xhtml-entity
  '((copy . "\u00a9")
    (nbsp . "\u00a0")
    (trade . "\u2122")))

(define (xhtml->sxml port)
  (with-module sxml.ssax
    (fluid-let ((ssax:predefined-parsed-entities
		 `(,@(with-module user xhtml-entity)
		   ,@ssax:predefined-parsed-entities)))
      (ssax:xml->sxml port '((xhtml . "http://www.w3.org/1999/xhtml"))))))

紙面の都合で一部の実体参照以外は省略した。

with-module は他のモジュール内部に入り込む構文であり、 export されていない定義にさえ触れることができる。 そのモジュールとしては弄られることを想定していないものを弄るわけだから、なるべく使用を避けるべきものであるが、応急処置にはなにかと便利なこともある。 「現実の問題」を相手にした Gauche らしい特徴だと思う。

(r6rs ではたとえ export されていても直接の代入は出来ない。)

fluid-let についてはマルチスレッドとの相性が悪かったりするので注意すること!

Document ID: 7b8505d25ec4b3b30c5b6e6c8b5f6278