googleAPIから天気の取得
clojure.xmlのparseにhtmlの文字列を渡せば{:tag :attrs :content)の木として取り出せる。
これをlazy-sequenceにしてfilterをかけていって取り出せばいいのかな?
たぶんだけどxpathのようなものが使えるライブラリがどこかにあるはず。どこにあるんだろう?
見つからなかったので、今回は"//a/b/c"のようなxpathだけを認識する関数を作ってそれを利用してみました。
tree-seqとenumration-seq,iterator-seqがあればほとんど何でもlazy-sequenceに出来そう…と思ったらxml-seqが既にありました。
(xml-seqはtree-seqを使って作られているのでtree-seqの使い方の参考にはなるかもしれません。)
(use '[clojure.xml :only (parse)]) ;;xpathではないかも。//a/b/cなどが有効なだけ (defn- tx-split [str] (map keyword (. str split "/"))) (defn tx-some [xpath-seq xml-seq] (reduce (fn [r ele] (filter #(= (:tag %) ele) r)) xml-seq xpath-seq)) (defn tx-strict [xpath-seq xml-seq] (let [[x & xs] xpath-seq children (filter #(= (:tag %) x) xml-seq)] (when children (tx-some xs (xml-seq children))))) (defn tiny-xpath [xpath xml] (if (. xpath startsWith "//") (tx-some (tx-split (. xpath substring 2)) (xml-seq xml)) (tx-strict (tx-split xpath) xml))) ;;; main (defn describe-weather [area-name] (let [url (format "http://www.google.com/ig/api?weather=%s" area-name) xml-obj (parse url)] (doseq [e (:content (first (tiny-xpath "//current_conditions" xml-obj)))] (println (:tag e) (:data (:attrs e)))))) (describe-weather "Tokyo") ;tokyoの人は楽しそうだ ;; user=> :condition Overcast ;; :temp_f 37 ;; :temp_c 3 ;; :humidity Humidity: 73% ;; :icon /ig/images/weather/cloudy.gif ;; :wind_condition Wind: NE at 6 mph