Clojure XML流关闭异常

Clojure XML流关闭异常,xml,clojure,xml-parsing,Xml,Clojure,Xml Parsing,我在解析带有clojure.data.XML的XML文件时遇到异常,因为在解析完成之前流已关闭 我不明白的是,为什么doall在with open关闭XML数据之前不强制对其求值(如所建议的): 这会引发异常: (file->xml "example.xml") ;-> XMLStreamException ParseError at [row,col]:[80,1926] Message: Stream closed com.sun.org.apache.xerces.intern

我在解析带有
clojure.data.XML
的XML文件时遇到异常,因为在解析完成之前流已关闭

我不明白的是,为什么
doall
with open
关闭XML数据之前不强制对其求值(如所建议的):

这会引发异常:

(file->xml "example.xml")
;-> XMLStreamException ParseError at [row,col]:[80,1926]
Message: Stream closed com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next
如果我用open包装器删除
,它将按预期返回XML数据(因此,尽管不能保证读卡器已关闭,但该文件是合法的)

我发现
(源xml/parse)
会产生惰性结果:

(defn parse
  "Parses the source, which can be an
   InputStream or Reader, and returns a lazy tree of Element records. 
   Accepts key pairs with XMLInputFactory options, see http://docs.oracle.com/javase/6/docs/api/javax/xml/stream/XMLInputFactory.html
   and xml-input-factory-props for more information. 
   Defaults coalescing true."
   [source & opts]
     (event-tree (event-seq source opts)))
也许这是相关的,但我的函数与上的“往返”示例非常相似


我在这里遗漏了什么?

看到这种行为我很惊讶。似乎
clojure.data.xml.Element
(返回类型)实现了一种“惰性映射”,它不受
doall
的影响

以下是将惰性值转换为法线贴图的解决方案:

(ns tst.clj.core
  (:use clj.core clojure.test tupelo.test)
  (:require
    [tupelo.core :as t]
    [clojure.string :as str]
    [clojure.pprint :refer [pprint]]
    [clojure.java.io :as io]
    [clojure.data.xml :as xml]
    [clojure.walk :refer [postwalk]]
  ))
(t/refer-tupelo)

(defn unlazy
  [coll]
  (let [unlazy-item (fn [item]
                      (cond
                        (sequential? item) (vec item)
                        (map? item) (into {} item)
                        :else item))
        result    (postwalk unlazy-item coll) ]
    result ))

(defn file->xml [path]
  (with-open [rdr (-> path io/resource io/reader) ]
    (let [lazy-vals    (xml/parse rdr)
          eager-vals   (unlazy lazy-vals) ]
      eager-vals)))
(pprint (file->xml "books.xml"))

{:tag :catalog,
 :attrs {},
 :content
 [{:tag :book,
   :attrs {:id "bk101"},
   :content
   [{:tag :author, :attrs {}, :content ["Gambardella, Matthew"]}
    {:tag :title, :attrs {}, :content ["XML Developer's Guide"]}
    {:tag :genre, :attrs {}, :content ["Computer"]}
    {:tag :price, :attrs {}, :content ["44.95"]}
    {:tag :publish_date, :attrs {}, :content ["2000-10-01"]}
    {:tag :description,
     :attrs {},
     :content
     ["An in-depth look at creating applications\n      with XML."]}]}
  {:tag :book,
   :attrs {:id "bk102"},
   :content
   [{:tag :author, :attrs {}, :content ["Ralls, Kim"]}
    {:tag :title, :attrs {}, :content ["Midnight Rain"]}
    {:tag :genre, :attrs {}, :content ["Fantasy"]}
    {:tag :price, :attrs {}, :content ["5.95"]}
    {:tag :publish_date, :attrs {}, :content ["2000-12-16"]}
    {:tag :description,
     :attrs {},
     :content
     ["A former architect battles corporate zombies,\n      an evil sorceress, and her own childhood to become queen\n      of the world."]}]}
  {:tag :book,
   :attrs {:id "bk103"},
   :content .....
由于
clojure.data.xml.Element
实现了
clojure.lang.IPersistentMap
,因此使用
(map?项)
返回true

这是你的电话号码

请注意:
clojure.data.xml
clojure.xml
不同。您可能需要浏览这两个库,以找到最适合您需要的库

您还可以在需要时使用
crossclj.info
查找api文档:

更新:
在看到这个问题大约一周后,我遇到了一个XML解析问题,就像这个问题一样,需要
unlazy
函数。你现在可以找到
unlazy

Hmm。很有趣。谢谢你花时间澄清发生了什么。我不会把这称为对道尔的“免疫”;它似乎是另一种懒惰的东西,一种懒惰序列的懒惰序列。我还没有深入研究源代码,但它似乎是一种“懒惰映射”类型的结构,在
datomic.query.EntityMap
中也可以看到。我认为问题在于
doall
仅用于惰性序列,而不是“惰性映射”。
(ns tst.clj.core
  (:use clj.core clojure.test tupelo.test)
  (:require
    [tupelo.core :as t]
    [clojure.string :as str]
    [clojure.pprint :refer [pprint]]
    [clojure.java.io :as io]
    [clojure.data.xml :as xml]
    [clojure.walk :refer [postwalk]]
  ))
(t/refer-tupelo)

(defn unlazy
  [coll]
  (let [unlazy-item (fn [item]
                      (cond
                        (sequential? item) (vec item)
                        (map? item) (into {} item)
                        :else item))
        result    (postwalk unlazy-item coll) ]
    result ))

(defn file->xml [path]
  (with-open [rdr (-> path io/resource io/reader) ]
    (let [lazy-vals    (xml/parse rdr)
          eager-vals   (unlazy lazy-vals) ]
      eager-vals)))
(pprint (file->xml "books.xml"))

{:tag :catalog,
 :attrs {},
 :content
 [{:tag :book,
   :attrs {:id "bk101"},
   :content
   [{:tag :author, :attrs {}, :content ["Gambardella, Matthew"]}
    {:tag :title, :attrs {}, :content ["XML Developer's Guide"]}
    {:tag :genre, :attrs {}, :content ["Computer"]}
    {:tag :price, :attrs {}, :content ["44.95"]}
    {:tag :publish_date, :attrs {}, :content ["2000-10-01"]}
    {:tag :description,
     :attrs {},
     :content
     ["An in-depth look at creating applications\n      with XML."]}]}
  {:tag :book,
   :attrs {:id "bk102"},
   :content
   [{:tag :author, :attrs {}, :content ["Ralls, Kim"]}
    {:tag :title, :attrs {}, :content ["Midnight Rain"]}
    {:tag :genre, :attrs {}, :content ["Fantasy"]}
    {:tag :price, :attrs {}, :content ["5.95"]}
    {:tag :publish_date, :attrs {}, :content ["2000-12-16"]}
    {:tag :description,
     :attrs {},
     :content
     ["A former architect battles corporate zombies,\n      an evil sorceress, and her own childhood to become queen\n      of the world."]}]}
  {:tag :book,
   :attrs {:id "bk103"},
   :content .....