Clojure数据zip xml组成

时间:2015-01-14 16:10:52

标签: 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/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)然后如上所述链接它们。即从顶部开始,从每个级别中选择内容,如果需要调用一个方法,以相同的方式进一步处理子级(使用拉链)。

换句话说 - 我想:

  1. 创建拉链
  2. 将拉链转发给其中一种处理方法
  3. 将拉链移动到特定位置
  4. 处理该位置
  5. 使用步骤3中设置的位置以相同的方式处理子项(步骤2. - 5.)
  6. 但是,基于f2中的异常,看起来它不起作用。如何才能做到这一点?如果不是人们应该如何使用clojure.data.zip.xml,那么推荐的是什么,考虑到分解?

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题。有一个非常简单的原因,你不能连续调用两个xml->运算符。正如Alex xml->已经提到的那样,返回一个seq。 你的问题有两个答案。 以惯用方式处理树(或XML文档)的一种方法是处理树的每个级别:

(map (fn [entry] (xml-> entry :title text))
 (get-entries atom1z))

如果您真正想要的是组合拉链,那么您必须编写一个宏来构建最终拉链,如get-entries-titles中的拉链。但是,只有在实际帮助您时才应使用宏。仔细想想。为了处理XML,你在clojure.data.zip.xml中缺少什么?