Does anyone know of a namespace aware xml parser / zipper?
Rather than having to pull in a whole bunch of axis or similar libs, I was hoping to parse the following:
(ns foo
(:require [clojure.zip :as zip]
[clojure.xml :as xml])
(:use clojure.data.zip.xml))
(def xml "<soap:Envelope xmlns=\"urn:WEBSERVICE-URN\"
xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
<soap:Body>
<loginResponse>
<result>
<sessionKey>SESSION-KEY-HERE</sessionKey>
</result>
</loginResponse>
</soap:Body>
</soap:Envelope>")
(def root
(zip/xml-zip
(xml/parse
(java.io.ByteArrayInputStream. (.getBytes xml "UTF-8")))))
(def key (xml1-> root ???? ???? :loginResponse :result :sessionKey text))
I can't seem to navigate the xml elements that have XML namespaces?
I think your problem here might be your use of xml1-> and not the namespaces in the XML. The tag= predicate in the XML zip namespace (which is implied when using keywords with xml1->) defaults to auto-descent mode, meaning that it descends to the children of the current node before trying to match element tags. Since the root element is already a soap:Envelope, you don't need to include that filter in the list with xml1->. The following should give you what you're looking for:
(xml1-> root :soap:Body :loginResponse :result :sessionKey text)
Note that element qnames are used in their unexpanded form as tag names in clojure.xml, and it's perfectly fine to have a keyword whose name contains a colon.
Alternatively, you could say:
(require '[clojure.data.zip :as zf])
(xml1-> (zf/auto false root)
:soap:Envelope :soap:Body :loginResponse :result :sessionKey text)
If you still require a namespace-aware XML parser, there's one in data.xml, though it simply discards namespace declarations and uses local names only:
(require '[clojure.data.xml :as data-xml])
(def root (-> (java.io.StringReader. xml) data-xml/parse zip/xml-zip)
(xml1-> root :Body :loginResponse :result :sessionKey text)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With