Insertions into Zipper trees on XML files in Clojure

偶尔善良 提交于 2019-11-30 19:34:39

Firstly, you should use :content (and not :contents) in your definition of Fred.

With that change in place, the following seems to work:

(-> (zf/xml-> @db :item) ; a convenient way to get to the :item zipper locs
    first                ; but we actually need just one
    zip/rightmost        ; let's move to the rightmost sibling of the first :item
                         ; (which is the last :item in this case)
    (zip/insert-right fred-item) ; insert Fred to the right
    zip/root)            ; get the modified XML map,
                         ; which is the root of the modified zipper

Your append-item2 is very similar, there are just two corrections to make:

  1. zf/xml-> returns a sequence of zipper locs; zip/rightmost accepts just one, so you have to fish one out first (hence the first in the above);

  2. after you're done modifying the zipper, you need to use zip/root to get back at (the modified version of) the underlying tree.

As a final note on style, print + format = printf. :-)

In create-item you mistyped :contents for :content and you should prefer vectors to lists for literals.

(I was going to make a more comprehensive answer but Michal as already written a pretty good one.)

An alternative to zip-filter is Enlive:

(require '[net.cgrand.enlive-html :as e]) ;' <- fix SO colorizer

(def db (ref (-> "itemdb.xml" java.io.File. e/xml-resource))

(defn create-item [name desc]
  {:tag :item
   :attrs {:id "3"}
   :content [{:tag :name :attrs {} :content [name]}
             {:tag :desc :attrs {} :content [desc]}]})

(def fred-item (create-item "Fred" "Green-haired astrophysicist."))

(dosync (alter db (e/transformation [:itemlist] (e/append fred-item))))
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!