Vesna
Vesna

Reputation: 345

clojure: creating vector of maps from xml

I have a question of how to perform a select * style "query" for xml files in clojure. Say, I have this XML, that you can get from this URL http://api.eventful.com/rest/events/search?app_key=4H4Vff4PdrTGp3vV&keywords=music&location=Belgrade&date=Future (if I paste it here it doesn't look good)

I want to get a vector of maps (map with tags as keys and its values), for all the repeating "rows" in the XML. So that every map is a event in this example XML. I can parse it, and make a zipper structure of it. Also I know how to do it using struct maps, but I want a more general solution, for any given xml, and maybe some starting tags from which to start. What I want is opposite from this Simple Clojure XML edit. Any idea would be great!

Thanks!

Upvotes: 2

Views: 708

Answers (1)

Ivan Koblik
Ivan Koblik

Reputation: 4325

You should take a look at enlive. It will transform XML into different list/map based structure and allow queries against it.

For example to select all the events you'd have to do the following:

(require '[net.cgrand.enlive-html :as html])
(def data (html/xml-resource "your.xml"))
(html/select data [:events])

To get all the event titles:

(select data [:even :title :*])

I haven't used it for a couple of months so I'm a little rusty. But there's a lot of material online.

EDIT:

You can actually use zippers to navigate data structure created by xml-resource. Here's an example where I look for any link with word bank in it and walk up from it to get its parent node.

(require [net.cgrand.enlive-html :as html])
(require [net.cgrand.xml :as xml])
(require [clojure.zip :as z])

(map
  (comp z/node z/up)
  (@#'html/zip-select-nodes*
   (map xml/xml-zip (html/html-resource page2))
   (@#'html/automaton
    [:a (html/re-pred #".*[Bb]ank.*")])))

I have to use @#' as functions zip-select-nodes* and automaton are namespace private.

Upvotes: 2

Related Questions