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))])