首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Clojure中的XML文件插入到Zipper树中

将Clojure中的XML文件插入到Zipper树中
EN

Stack Overflow用户
提问于 2010-05-20 18:37:06
回答 2查看 1.7K关注 0票数 9

我感到困惑的是,如何以惯常的方式更改通过clojure.contrib的zip-filter.xml访问的xml树。应该尝试这样做,还是有更好的方法?

假设我有一个虚拟的xml文件"itemdb.xml“,如下所示:

代码语言:javascript
复制
<itemlist> 
  <item id="1">
    <name>John</name>
    <desc>Works near here.</desc>
  </item>
  <item id="2">
    <name>Sally</name>
    <desc>Owner of pet store.</desc>
  </item>
</itemlist>

我有一些代码:

代码语言:javascript
复制
(require '[clojure.zip :as zip]
  '[clojure.contrib.duck-streams :as ds]
  '[clojure.contrib.lazy-xml :as lxml]
  '[clojure.contrib.zip-filter.xml :as zf]) 

(def db (ref (zip/xml-zip (lxml/parse-trim (java.io.File. "itemdb.xml")))))

;; Test that we can traverse and parse.
(doall (map #(print (format "%10s: %s\n"
       (apply str (zf/xml-> % :name zf/text))
       (apply str (zf/xml-> % :desc zf/text))))
     (zf/xml-> @db :item)))

;; I assume something like this is needed to make the xml tags
(defn create-item [name desc]
  {:tag :item
   :attrs {:id "3"}
   :contents
   (list {:tag :name :attrs {} :contents (list name)}
         {:tag :desc :attrs {} :contents (list desc)})})

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

;; This disturbs the structure somehow
(defn append-item [xmldb item]
  (zip/insert-right (-> xmldb zip/down zip/rightmost) item))

;; I want to do something more like this
(defn append-item2 [xmldb item]
  (zip/insert-right (zip/rightmost (zf/xml-> xmldb :item)) item))

(dosync (alter db append-item2 fred-item))

;; Save this simple xml file with some added stuff.
(ds/spit "appended-itemdb.xml"
    (with-out-str (lxml/emit (zip/root @db) :pad true)))

我不清楚如何在这种情况下适当地使用clojure.zip函数,以及它如何与zip-filter交互。

如果你在这个小例子中发现了什么特别奇怪的地方,请指出它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-21 01:41:00

首先,你应该在你的Fred定义中使用:content (而不是:contents)。

有了这样的改变,下面的方法似乎是可行的:

代码语言:javascript
复制
(-> (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

您的append-item2非常相似,只有两处需要更正:

  1. zf/xml->返回一个拉链locs序列;zip/rightmost只接受一个,所以您必须首先搜索一个(因此是上面的first );
  2. 完成拉链修改后,您需要使用zip/root返回底层树(修改后的版本)。

作为样式的最后说明,print + format = printf。:-)

票数 8
EN

Stack Overflow用户

发布于 2010-05-21 02:00:39

在create-item中,您错误地键入了:contents for :content,您应该优先选择向量而不是lists来获取文字。

(我打算做一个更全面的回答,但Michal已经写了一个很好的答案。)

zip-filter的另一种选择是Enlive:

代码语言:javascript
复制
(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))))
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2872921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档