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