Clojure XML流关闭异常 [英] Clojure XML Stream Closed Exception

查看:87
本文介绍了Clojure XML流关闭异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 clojure.data.xml 解析XML文件时遇到异常,因为流在​​解析完成之前就关闭了。

I am getting an exception parsing an XML file with clojure.data.xml, because the stream is closing before the parsing is complete.

我不明白的是为什么 doall 不强制在<$ c $之前执行XML数据评估c> with-open 将其关闭(如此相关答案所建议):

What I do not understand is why doall is not forcing the evaluation of the XML data before with-open closes it (as suggested by 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数据(因此文件是合法的,尽管不能保证读者可以关闭。)

If I remove the with-open wrapper, it returns the XML data as expected (so the file is legit though the reader is not guaranteed closed).

我看到(源xml / parse)会产生懒惰的结果:

I see that (source xml/parse) yields lazy results:

(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自述文件。

so perhaps that is related, but the function I have is very similar to the "round-trip" example on the clojure.data.xml README.

我在这里缺少什么?

推荐答案

我很惊讶地看到这种行为。看来 clojure.data.xml.Element (返回类型)实现了一种懒惰图类型,不受 doall的影响

I was surprised to see this behavior. It appears that clojure.data.xml.Element (the return type) implements a type of "lazy map" that is immune to the effects of doall.

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

Here is a solution which transforms the lazy values into normal maps:

(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 。 item)返回true。

Since clojure.data.xml.Element implements clojure.lang.IPersistentMap, using (map? item) returns true.

这是 books.xml的示例数据

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

clojure.data.xml is different that clojure.xml. You may need to explore both libraries to find the one that fits your needs best.

  • https://clojuredocs.org/clojure.xml
  • https://github.com/clojure/data.xml

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

You can also use crossclj.info to find api docs when needed:

  • https://crossclj.info/doc/org.clojure/clojure/latest/clojure.xml.html
  • https://crossclj.info/doc/org.clojure/data.xml/0.2.0-alpha2/index.html

一周后我看到这个问题碰到了XML解析问题就像需要 unlazy 函数的那个​​一样。现在,您可以在图珀洛(Tupelo)库中找到懒惰的

Just a week or so after I saw this question I ran into an XML parsing problem just like this one that needed the unlazy function. You can now find unlazy in the Tupelo library.

这篇关于Clojure XML流关闭异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆