sxml の簡易シリアライズ
SXML (http://ja.wikipedia.org/wiki/SXML) の名前空間部分を無視して文字列化する、簡単なシリアライザーを gauche で書いた。
以下使用例。生成された文字列と、その前段階のリストを同時に返している。
gosh> (simple-sxml->xml '(tag)) "<tag/>" ("<" "tag" () "/>") gosh> (simple-sxml->xml '(html (@ (lang "ja")) (body))) "<html lang=\"ja\"><body/></html>" ("<" #0="html" ((" " "lang" "=\"" "ja" "\"")) ">" (("<body/>")) "</" #0# ">") gosh> (simple-sxml->xml '(tag (@ (attr1 "v1") (attr2 "v2")) (nested "Text Node") (empty))) "<tag attr1=\"v1\" attr2=\"v2\"><nested>Text Node</nested><empty/></tag>" ("<" #0="tag" ((#1=" " "attr1" #2="=\"" "v1" #3="\"") (#1# "attr2" #2# "v2" #3#)) ">" (("<nested>Text Node</nested>" "<empty/>")) "</" #0# ">")
パターンマッチには util.match を使う。string-append を使って文字列を逐次生成するのは冗長に感じられたので、一旦文字列のリストを生成した後、 text.tree で文字列にすることにした。
(use util.match) (use text.tree) (define (simple-sxml->xml x) (define (rep1 x attrs) `("<" ,(symbol->string x) ,attrs "/>")) (define (rep x attrs . body) (let1 s (symbol->string x) `("<" ,s ,attrs ">" ,body "</" ,s ">"))) (define (iter tree) (match x ((tag) (rep1 tag '())) ((tag ('@ (attr value) ...)) (rep1 tag (map (lambda (a v) (list " " (symbol->string a) "=\"" v "\"")) attr value))) ((tag ('@ (attr value) ...) rest ...) (rep tag (map (lambda (a v) (list " " (symbol->string a) "=\"" v "\"")) attr value) (map simple-sxml->xml rest))) ((tag rest ...) (rep tag '() (map simple-sxml->xml rest))) (() "") ((? string? s) s))) (let1 r (iter x) (values (tree->string r) r)))