Clojureデータ構造をXMLにシリアル化する必要がありますが、コレクションを発行する方法に出くわしています。これをより具体的にするために、次のようにClojureマップがあると仮定します。
(def parking-lot {:parking-lot #{
{:car {:color "red", :make "nissan", :year 2003}}
{:car {:color "blue", :make "toyota", :year 2001}}
{:car {:color "black", :make "honda", :year 2010}}}})
これは、値が「車」アイテムのセットである1つの要素を持つ単なるマップです。ここで、このマップをシリアル化して次のXMLを生成するとします。
<? xml version="1.0" ?>
<parking-lot>
<car color="red" make="nissan" year="2003" />
<car color="blue" make="toyota" year="2001" />
<car color="black" make="black" year="2010" />
</parking-lot>
ClojureでXMLを最適に解析/出力する方法に関するドキュメントをWebで検索すると、clojure.data.xmlライブラリが表示されたので、それを使用しています。
clojure.data.xmlを使用してXMLを出力する方法の簡単な例を次に示します。
REPL> (use 'clojure.data.xml)
=> nil
REPL> (emit-str (element :parking-lot {}))
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<parking-lot></parking-lot>"
もう少し複雑な例:
REPL> (emit-str (element :parking-lot {}
(element :car {:color "yellow" :make "ford" :year "2000"})
(element :car {:color "purple" :make "chevrolet" :year "1977"})))
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<parking-lot>
<car color=\"yellow\" year=\"2000\" make=\"ford\"></car>
<car color=\"purple\" year=\"1977\" make=\"chevrolet\"></car>
</parking-lot>"
ここで、「element」関数の3番目の引数は、実際には「element」への可変数の呼び出しである可能性があることがわかります。'element'関数のドキュメントを詳しく調べずに、'element'がオーバーロードされて、一連の要素アイテムも3番目の引数として使用されると思いました。そのため、ドキュメントを見ずに、先に進んで、それを実行するコードの小さなブロックを作成しました。
REPL> (emit-str (element :parking-lot {}
(map (fn [car] (let [carattrs (:car car)]
(element :car {:color (:color carattrs),
:make (:make carattrs),
:year (:year carattrs)})))
(:parking-lot parking-lot))))
私はこれがうまくいくことを望んでいましたが、残念ながらそうではありません。問題は、「element」関数の3番目の引数をシーケンス自体にすることはできないということです。
ですから、この時点で私は何をすべきかについて少し困惑しています。私はまだLispとClojureに比較的慣れていないので、次の考えがモロニックであるなら、私を楽にしてください。だから私の考えは、これはマクロのユースケースでしょうか?つまり、車のセット(またはそのことについては任意のcoll)を入力として受け取り、そのアイテムを個々のs式として出力するマクロを作成する必要がありますか?たとえば、次のように動作するマクロを頭の中で考えています。
REPL> (defmacro flatten-as-elements [coll-of-cars] ...)
REPL> (flatten-as-elements #{ {:color "blue" :model "honda" year "2000"}
{:color "yellow" :model "ford" year "2011"}})
=> (element :car {:color "blue" :model "honda" year "2000"})
(element :car {:color "yellow" :model "ford" year "2011"})
少なくとも私の考えでは、そのようなマクロの出力は、「要素」関数の3番目の引数として適合し、私の目的の目標を生成します。もちろん、私の心配は、私が見落としている完全に明白な解決策がいくつかあり、ここでマクロを使用することは誤った方向に進んでいることです。SOコミュニティからの助けは大歓迎です!前もって感謝します!
-ポール