Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic way to build a custom structure from XML zipper in Clojure

Tags:

xml

clojure

Say, I'm parsing an RSS feed and want to extract a subset of information from it.

(def feed (-> "http://..." clojure.zip/xml-zip clojure.xml/parse))

I can get links and titles separately:

(xml-> feed :channel :item :link text)
(xml-> feed :channel :item :title text)

However I can't figure out the way to extract them at the same time without traversing the zipper more than once, e.g.

(let [feed (-> "http://..." clojure.zip/xml-zip clojure.xml/parse)]
    (zipmap 
        (xml-> feed :channel :item :link text)
        (xml-> feed :channel :item :title text)))

...or a variation of thereof, involving mapping multiple sequences to a function that incrementally builds a map with, say, assoc.

Not only I have to traverse the sequence multiple times, the sequences also have separate states, so elements must be "aligned", so to speak. That is, in a more complex case than RSS, a sub-element may be missing in particular element, making one of sequences shorter by one (there are no gaps). So the result may actually be incorrect.

Is there a better way or is it, in fact, the way you do it in Clojure?

like image 490
Alex B Avatar asked May 07 '10 11:05

Alex B


1 Answers

What about this?

(reduce (fn [h item] 
          (assoc h (xml1-> item :title text) 
                   (xml1-> item :link text))) 
        {} (xml-> feed :channel :item))
like image 84
Brian Carper Avatar answered Nov 05 '22 12:11

Brian Carper