Collections 将org.w3c.dom.NodeList转换为Clojure ISeq

Collections 将org.w3c.dom.NodeList转换为Clojure ISeq,collections,clojure,Collections,Clojure,我正在尝试处理新的defprotocol,reify等 我有一个从XPath调用返回的org.w3c.dom.NodeList,我想将其“转换”为ISeq 在Scala中,我实现了一种隐式转换方法: implicit def nodeList2Traversable(nodeList: NodeList): Traversable[Node] = { new Traversable[Node] { def foreach[A](process: (Node) => A) {

我正在尝试处理新的
defprotocol
reify

我有一个从XPath调用返回的
org.w3c.dom.NodeList
,我想将其“转换”为ISeq

在Scala中,我实现了一种隐式转换方法:

implicit def nodeList2Traversable(nodeList: NodeList): Traversable[Node] = {
  new Traversable[Node] {
    def foreach[A](process: (Node) => A) {
      for (index <- 0 until nodeList.getLength) {
        process(nodeList.item(index))
      }
    }
  }
}
隐式def nodeList2Traversable(nodeList:nodeList):可遍历[Node]={
新的可遍历[节点]{
def foreach[A](进程:(节点)=>A){
对于(索引使用a),这些产生惰性序列

这是为您编写的代码。我花了一些时间让它在命令行上运行;您只需要替换已解析XML文件的名称

注意事项1:避免定义变量。改用局部变量

注意事项2:这是用于XML的Java API,因此对象是可变的;因为您有一个惰性序列,如果在迭代时可变DOM树发生任何更改,您可能会有不愉快的竞争更改

注意事项3:即使这是一个惰性结构,整个DOM树也已经在内存中了(不过我不确定最后一条评论。我认为API试图推迟在需要时读取内存中的树,但没有保证)。因此,如果您遇到大XML文档的问题,请尝试避免使用DOM方法

(require ['clojure.java.io :as 'io])
(import [javax.xml.parsers DocumentBuilderFactory])
(import [org.xml.sax InputSource])

(def dbf (DocumentBuilderFactory/newInstance))
(doto dbf
  (.setValidating false)
  (.setNamespaceAware true)
  (.setIgnoringElementContentWhitespace true))
(def builder (.newDocumentBuilder dbf))
(def doc (.parse builder (InputSource. (io/reader "C:/workspace/myproject/pom.xml"))))

(defn lazy-child-list [element]
  (let [nodelist (.getChildNodes element)
        len (.getLength nodelist)]
    (for [i (range len)]
      (.item nodelist i))))

;; To print the children of an element
(-> doc
    (.getDocumentElement)
    (lazy-child-list)
    (println))

;; Prints clojure.lang.LazySeq
(-> doc
    (.getDocumentElement)
    (lazy-child-list)
    (class)
    (println))

Clojure的大多数序列处理函数返回惰性序列,包括
map
range
函数:

(defn node-list-seq [^org.w3c.dom.NodeList node-list]
  (map (fn [index] (.item node-list index))
       (range (.getLength node-list))))
注意,上面的NodeList类型提示不是必需的,但是可以提高性能

现在您可以像这样使用该函数:

(map #(.getLocalName %) (node-list-seq your-node-list))

我们的帖子错了,否则我就不会麻烦了。你用“for”在这里看起来很不错。