Reputation: 345
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
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