这是一个示例来说明我想做的事情:
(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))
运行f1
会产生预期的结果:
("clojure is the best lisp yet" "experimenting with vnc")
运行f2
抛出异常:
ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn clojure.zip/node (zip.clj:67)
我的目标是将处理分成几个步骤:
- 获取 xml
- 从 xml 中获取条目
- 从条目中获取标题
这样我就可以把事情分成不同的方法。例如,我可能需要提取属于 XML 不同部分的元素的不同属性,从而生成一个扁平的输出集合(例如,<id>
从 atom1 上获取所有元素,生成一个 ID 向量)。
我想要处理每种类型的节点的方法(在上面的示例中,从 获取 IDfeed
并从 获取 ID entry
)然后将它们链接起来。即从顶部下降,从每个级别中挑选东西,如果需要调用以相同方式进一步处理子项的方法(使用拉链)。
换句话说 - 我想:
- 创建一个拉链
- 将该拉链转发到一种处理方法
- 将拉链移动到特定位置
- 处理该位置
- 使用步骤 3 中设置的位置以相同的方式处理子项(步骤 2. - 5.)
但是,根据f2
. 如何才能做到这一点?如果这不是人们应该如何使用 clojure.data.zip.xml,那么在考虑分解的情况下,推荐的会是什么?