2017-04-03 12 views
3

解析が完了する前にストリームが閉じているので、clojure.data.xmlのXMLファイルを解析する例外が発生します。私は理解していない何Clojure XMLストリームクローズ例外

は(this related answerにより示唆されるように)with-openがそれを閉じる前doallは、XMLデータの評価を強制されていない理由は次のとおりです。

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

(: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)))) 

with-openラッパーを削除すると、期待通りにXMLデータが返されます(リーダは保証されていませんが、ファイルは正当なものです)。ので、おそらくそれが関連している

(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の「往復」の例と非常によく似ています

私は(source xml/parse)は怠惰な結果が得られていることがわかります。

私はここで何が欠けていますか?

答えて

3

私はこの動作を見て驚いた。 clojure.data.xml.Element(戻り値の型)は、doallの影響を受けないタイプの「遅延マップ」を実装しているようです。 clojure.data.xml.Elementが真(map? item)リターンを使用して、clojure.lang.IPersistentMapを実装するため

(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 ..... 

:ここ

は、法線マップに遅延値を変換するソリューションです。ここで

sample data for books.xml

です注意してください:

clojure.data.xmlclojure.xmlその異なっています。ニーズに最も適したライブラリを見つけるには、両方のライブラリを調べる必要があるかもしれません。

また、必要なときにAPIドキュメントを検索するためにcrossclj.infoを使用することができます。

更新:

ちょうど一週間ほど、私はちょうどunlazy機能を必要として、この1のようなXML構文解析の問題に遭遇したこの質問を見た後。今すぐunlazyin the Tupelo libraryを見つけることができます。

+0

Hmm。面白い。何が起こっているのかを明確にする時間をとってくれてありがとう。 – nrako

+0

私はこれを「免疫」と呼ぶことはありません。むしろレイジーシーケンスの怠惰なシーケンスである、レイジーなものの別の_level_であるかのように見えます。 – Svante

+0

私はソースコードを掘り下げませんでしたが、それは構造の "怠惰なマップ"タイプであると思われます。これは 'datomic.query.EntityMap'でも見られます。問題は '' doall''は ''レイジーマップ ''ではなく ''レイジーシーケンス ''のみを対象としていることだと思います。 –

関連する問題