2

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!

1
  • I know there is a clojure library for xpath, but I thought that I could do it using zippers...no luck though.... Commented Sep 14, 2012 at 18:38

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Zippers are cool, you can actually use them with Enlive, but it is a little hidden. I'll add to my answer info about it!
I was thinking something more like this: (->> (en-html/select xml-doc [:holiday]) (map en-html/text) (partition 2) (map #(zipmap [:name :month] %))). it works fine with this xml <calendar> <holiday type="International"> <name>International Lefthanders Day</name> <date> <month>August</month> <day>13</day> </date> </holiday> <holiday type="Personal"> <name>Rover's birthday</name> <date> <month>October</month> <day>12</day> </date> ... but not with mine. I can't get to select anything from my feed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.