Clojure数据压缩xml组合
下面是一个例子来说明我想做什么:Clojure数据压缩xml组合,xml,clojure,zipper,Xml,Clojure,Zipper,下面是一个例子来说明我想做什么: (ns sample (:require [clojure.zip :as zip] [clojure.data.zip.xml :refer [attr text xml-> xml1->]] [clojure.data.xml :as xml])) ;; From https://github.com/clojure/data.zip/blob/ca5a2efcc1c865baa25f904d
(ns sample
(:require [clojure.zip :as zip]
[clojure.data.zip.xml :refer [attr text xml-> xml1->]]
[clojure.data.xml :as xml]))
;; From https://github.com/clojure/data.zip/blob/ca5a2efcc1c865baa25f904d7d9f027809b8f738/src/test/clojure/clojure/data/zip/xml_test.clj
(def atom1 (xml/parse-str "<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'>
<id>tag:blogger.com,1999:blog-28403206</id>
<updated>2008-02-14T08:00:58.567-08:00</updated>
<title type='text'>n01senet</title>
<link rel='alternate' type='text/html' href='http://n01senet.blogspot.com/'/>
<entry>
<id>1</id>
<published>2008-02-13</published>
<title type='text'>clojure is the best lisp yet</title>
<author><name>Chouser</name></author>
</entry>
<entry>
<id>2</id>
<published>2008-02-07</published>
<title type='text'>experimenting with vnc</title>
<author><name>agriffis</name></author>
</entry>
</feed>
"))
(def atom1z (zip/xml-zip atom1))
(defn get-entries-titles [z]
(xml-> z :entry :title text))
(defn get-entries [z]
(xml-> z :entry))
(defn get-titles [z]
(xml-> z :title))
(defn f1 []
(-> atom1z get-entries-titles))
(defn f2 []
(-> atom1z get-entries get-titles text))
运行f2
会引发异常:
ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn clojure.zip/node (zip.clj:67)
我的目标是将处理分为几个步骤:
- 获取xml
- 从xml获取条目
- 从条目中获取标题
元素,生成一个ID向量)
我希望有一些方法可以处理每种类型的节点(在上面的示例中,从feed
获取ID,从entry
获取ID),然后如上所述链接它们。也就是说,从上往下,从每一层挑选东西,如果需要,调用一个方法,以同样的方式(使用拉链)进一步处理孩子们
换句话说,我想:
但是,根据
f2
中的异常情况,它看起来不是这样工作的。如何做到这一点?如果这不是使用clojure.data.zip.xml的方式,那么考虑到分解,建议使用哪种方式?我遇到了同样的问题。不能连续调用两个xml->
运算符的原因很简单。正如Alex已经提到的那样,xml->
返回一个seq。
你的问题有两个答案。
习惯处理树(或XML文档)的一种方法是处理树的每一级:
(map (fn [entry] (xml-> entry :title text))
(get-entries atom1z))
如果您真正想要的是组合拉链,那么您必须编写一个宏来构造最终的拉链,就像get entries标题中的拉链一样。但是,只有在宏确实有帮助的情况下,才应该使用它。仔细想想。为了处理xml,您在clojure.data.zip.xml中缺少了什么?
xml->
接受一个拉链并返回一个拉链序列。如果您想编写这样的函数,您需要重写它们以接受一个拉链序列。谢谢@Alex,这当然有道理(我甚至需要xml1->
…)。是否愿意发布一个我可以接受的答案?这是推荐的方法吗?有什么替代方法吗?你通常是如何处理这些事情的?
(map (fn [entry] (xml-> entry :title text))
(get-entries atom1z))