xml - Clojure 数据 zip xml 组合

标签 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),然后像上面那样链接它们。 IE。从顶部下降,从每个级别挑选东西,如果需要,调用一个方法以相同的方式(使用 zipper )进一步处理 child 。

换句话说——我想:

  1. 创建一个 zipper
  2. 将该 zipper 转发给其中一种处理方法
  3. 将 zipper 移动到特定位置
  4. 处理该位置
  5. 使用在步骤 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/

相关文章:

asynchronous - Clojure RethinkDB 订阅 changefeed

c# - 选择 XML 中的节点

c# - 如何使用 C# 检索特定的 XML 标签值

macros - 另一个宏中的 Clojure 宏 : how to generate string from symbol

database - 在ring网站中使用atom作为内存数据库

scala - 用 Zipper 解决 Twitter Puddle

异构树上的 Clojure Zipper

scala - 了解为什么 Zipper 是 Comonad

java - 将关联数组(Hashmap)作为参数传递给 xml rpc

java - 相对布局 fill_parent 问题