xmlをパースして、ツリー探索でHiccup形式に変換して、もと通りに戻す

Clojureで、xmlをパースして、ツリー探索でHiccup形式に変換して、もと通りに戻すコードを書いてみた。
これをベースに、入力xmlファイル全体を舐めて変換する系のコードが書けそう♪

(ns xmlhello.core
  (:use [hiccup.core]
        [clojure.java.io :only (writer)])
  (:require [clojure.xml]))

(defn load-xml-seq
  [filepath]
;  (xml-seq (clojure.xml/parse (java.io.File. filepath))))
  [(clojure.xml/parse (java.io.File. filepath))])

(defn leaf? [x]
  ((complement map?) x))

(defn trace-tree
  [xmlseq]
  (map #(if (leaf? %)
              %
              [(:tag %)
               (:attrs %)
               (trace-tree (:content %))])
       xmlseq))

(defn convert
  [from to func]
  (with-open [w (writer to :encoding "UTF-8")]
    (.write w
      (html (func (load-xml-seq from))))))

(defn -main []
  (convert "in.xml" "out.xml" trace-tree))

例えばこんな感じ(2013/06/29追記)

上記の trace-tree を以下のように書き換え。
書き換え対象のタグ毎に defmethod を追加すれば良いつくりにしている。

(defn nodes? [x]
  (vector? x))

(defn node? [x]
  (map? x))

(defn leaf? [x]
  (not (or (nodes? x) (node? x))))

(defmulti trace-tree
  (fn [xmlseq & _]
    (cond (nodes? xmlseq) :_nodes
          (leaf?  xmlseq) :_leaf
          :default        (:tag xmlseq))))

(defmethod trace-tree :_nodes
  [xmlseq & _]
  (map trace-tree xmlseq))

(defmethod trace-tree :_leaf
  [xmlseq & _]
  xmlseq)

;デフォルト(そのタグを無視版)
;(defmethod trace-tree :default
;  [xmlseq & _]
;  (trace-tree (:content xmlseq)))

;デフォルト(そのタグをそのまま利用版)
(defmethod trace-tree :default
  [xmlseq & _]
  [(:tag  xmlseq)
   (:attrs xmlseq)
   (trace-tree (:content xmlseq))])

;【変換定義例】
;  <myinput:btn label="ボタン"/>を <input type="button" value="ボタン"/> に置換
(defmethod trace-tree :myinput:btn
  [xmlseq & _]
  [:input
    (merge
      {:type "button"
       :value (:label (:attrs xmlseq))}
      (dissoc (:attrs xmlseq) :label))
    (trace-tree (:content xmlseq))])
実行例
<root>
  <content>
    <myinput:btn label="ボタン"/>
    <hoge>
      hoge
    </hoge>
  </content>
</root>
<root>
  <content>
    <input type="button" value="ボタン"></input>
    <hoge>
        hoge
    </hoge>
  </content>
</root>