【问题标题】:Clojure XML Stream Closed ExceptionClojure XML 流关闭异常
【发布时间】:2017-04-03 20:59:16
【问题描述】:

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

我不明白为什么doall 不强制在with-open 关闭XML 数据之前对其进行评估(如this related answer 所建议):

(:require [clojure.java.io :as io]
          [clojure.data.xml :as xml])

(defn file->xml [path] 
  (with-open [rdr (-> path io/resource io/reader)] 
    (doall (xml/parse rdr))))

抛出异常:

(file->xml "example.xml")
;-> XMLStreamException ParseError at [row,col]:[80,1926]
Message: Stream closed com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next

如果我删除 with-open 包装器,它会按预期返回 XML 数据(因此文件是合法的,尽管不能保证阅读器已关闭)。

我看到 (source 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 README 上的“往返”示例非常相似。

我在这里错过了什么?

【问题讨论】:

    标签: xml clojure xml-parsing


    【解决方案1】:

    我很惊讶看到这种行为。似乎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? item) 返回true。

    这里是sample data for books.xml

    请注意:

    clojure.data.xmlclojure.xml 不同。您可能需要探索这两个库,才能找到最适合您需求的库。

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

    更新:

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

    【讨论】:

    • 嗯。有趣的。感谢您抽出宝贵时间澄清发生了什么。
    • 我不会将此称为“免疫”;它更像是另一个 level 的惰性事物,一个惰性序列的惰性序列。
    • 我没有深入研究源代码,但是看起来它是一种“惰性映射”类型的结构,在datomic.query.EntityMap中也可以看到。我认为问题在于doall 仅适用于惰性序列,而不是“惰性映射”。
    猜你喜欢
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 2019-12-03
    • 2012-09-10
    相关资源
    最近更新 更多