I'm finding the usage of xml-> extremely confusing. I've read the docs and the examples but can't figure out how to get the nested nodes of an xml doc.
Assume the following xml is in a zipper (as from xml-zip):
<html>
<body>
<div class='one'>
<div class='two'></div>
</div>
</body>
</html>
I am trying to return the div with class='two'.
I was expecting this to work:
(xml-> z :html :body :div :div)
Or this:
(xml-> z :html :body :div (attr= :class "two"))
Kind of like css selectors.
But it returns only the first level, and it doesn't search down through the tree.
The only way I can make it work is:
(xml-> z :html :body :div children leftmost?)
Is that what I'm supposed to do?
The whole reason I started using xml-> was for convenience and to avoid navigating the zipper up and down and left and right. If xml-> can not get nested nodes then I don't see the value over clojure.zip.
Thanks.
Two consequitive :div match the same node. You should have come down.
And I believe you've forgotten to get the node with zip/node.
(ns reagenttest.sample
(:require
[clojure.zip :as zip]
[clojure.data.zip.xml :as data-zip]))
(let [s "..."
doc (xml/parse (java.io.ByteArrayInputStream. (.getBytes s)))]
(prn (data-zip/xml-> (zip/xml-zip doc) :html :body :div zip/down (data-zip/attr= :class "two") zip/node)))
or you could use custom-made abstraction if you are not happy with xml->:
(defn xml->find [loc & path]
(let [new-path (conj (vec (butlast (interleave path (repeat zip/down)))) zip/node)]
(apply (partial data-zip/xml-> loc) new-path)))
Now you can do this:
(xml->find z :html :body :div :div)
(xml->find z :html :body :div (data-zip/attr= :class "two"))
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