Clojure XML流关闭异常 [英] Clojure XML Stream Closed Exception
问题描述
我在使用 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)))
所以也许这是相关的,但是我拥有的功能与往返非常相似
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
使用(地图?)实现
返回true。 clojure.lang.IPersistentMap
。 item)
Since clojure.data.xml.Element
implements clojure.lang.IPersistentMap
, using (map? item)
returns true.
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
- 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屋!