这里有一个例子来说明我想做什么:
(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 不同部分的元素的不同属性,从而产生一个扁平的输出集合(例如,从 atom1 中获取所有 <id>
元素,产生一个 ID 向量).
我想要处理每种类型节点的方法(在上面的示例中,从 feed
获取 ID 并从 entry
获取 ID),然后像上面那样链接它们。 IE。从顶部下降,从每个级别挑选东西,如果需要,调用一个方法以相同的方式(使用 zipper )进一步处理 child 。
换句话说——我想:
- 创建一个 zipper
- 将该 zipper 转发给其中一种处理方法
- 将 zipper 移动到特定位置
- 处理该位置
- 使用在步骤 3 中设置的位置,以相同的方式处理子项(步骤 2. - 5.)
但是,根据 f2
中的异常情况,它似乎不能那样工作.如何才能做到这一点?如果这不是人们应该如何使用 clojure.data.zip.xml,考虑到分解,推荐的是什么?
最佳答案
我遇到了同样的问题。不能连续调用两个 xml->
运算符的原因很简单。正如 Alex xml->
已经提到的那样,返回一个序列。
你的问题有两个答案。
一种惯用处理树(或 XML 文档)的方法是处理树的每一层:
(map (fn [entry] (xml-> entry :title text))
(get-entries atom1z))
如果您真正想要的是组合 zipper ,那么您必须编写一个宏来构建最终的 zipper ,就像 get-entries-titles 中的那样。但是,只有当它确实对您有帮助时,您才应该使用宏。谨慎思考。为了处理 XML,您从 clojure.data.zip.xml 中遗漏了什么?
关于xml - Clojure 数据 zip xml 组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27947433/