7

What is the easiest way to get the value of an element from an XML string in Clojure? I am looking for something like:

(get-value "<a><b>SOMETHING</b></a>)" "b")

to return

"SOMETHING"
yazz.com
  • 57,320
  • 66
  • 234
  • 385

6 Answers6

10

Zippers can be handy for xml, they give you xpath like syntax that you can mix with native clojure functions.

user=> (require '[clojure zip xml] '[clojure.contrib.zip-filter [xml :as x]])

user=> (def z (-> (.getBytes "<a><b>SOMETHING</b></a>") 
                  java.io.ByteArrayInputStream. 
                  clojure.xml/parse clojure.zip/xml-zip))

user=> (x/xml1-> z :b x/text)

returns

"SOMETHING"
user499049
  • 564
  • 2
  • 6
  • I would suggest this as best approach as it is not only more functional but also more easy to extend once you get hang of it.. so +1 for Zipper – Ash Aug 30 '11 at 17:10
7

I do not know how idiomatic Clojure it is but if you happen to know and like XPath it can be used quite easily in Clojure due to its excellent interoperability with Java:

(import javax.xml.parsers.DocumentBuilderFactory) 
(import javax.xml.xpath.XPathFactory)

(defn document [filename]
  (-> (DocumentBuilderFactory/newInstance)
      .newDocumentBuilder
      (.parse filename)))

(defn get-value [document xpath]
  (-> (XPathFactory/newInstance)
      .newXPath
      (.compile xpath)
      (.evaluate document)))

user=> (get-value (document "something.xml") "//a/b/text()")
"SOMETHING"
Jonas
  • 19,422
  • 10
  • 54
  • 67
6

Using Christophe Grand's great Enlive library:

(require '[net.cgrand.enlive-html :as html])

(map html/text
     (html/select (html/html-snippet "<a><b>SOMETHING</b></a>")  [:a :b]))
Jürgen Hötzel
  • 18,997
  • 3
  • 42
  • 58
5

Try this:

user=> (use 'clojure.xml)

user=> (for [x (xml-seq 
          (parse (java.io.File. file)))
             :when (= :b (:tag x))]
     (first (:content x)))

Check this link for more info.

Hasan Fahim
  • 3,875
  • 1
  • 30
  • 51
2

Using clj-xpath, ( https://github.com/brehaut/necessary-evil ) :

(use 'com.github.kyleburton.clj-xpath :only [$x:text])
($x:text "/a/b" "<a><b>SOMETHING</b></a>)")
Laurent Petit
  • 1,201
  • 7
  • 12
1

Is this: Clojure XML Parsing not what you want? An alternative (external) source is here: http://blog.rguha.net/?p=510 .

Community
  • 1
  • 1
steenhulthin
  • 4,553
  • 5
  • 33
  • 52