parse-seq(clojure.contrib.lazy-xml)

Parses the source s, which can be a File, InputStream or String naming a URI. Returns a lazy sequence of maps with two or more of the keys :type, :name, :attrs, and :str. Other SAX-compatible parsers can be supplied by passing startparse, a fn taking a source and a ContentHandler and returning a parser. If a parser is specified, it will be run in a separate thread and be allowed to get ahead by queue-size items, which defaults to maxing. If no parser is specified and org.xmlpull.v1.XmlPullParser is in the classpath, this superior pull parser will be used.

; clojure/contrib/lazy_xml.clj:37
(defn parse-seq
  ([s] (if has-pull
         (parse-seq-pull s)
         (parse-seq s startparse-sax)))
  ([s startparse] (parse-seq s startparse Integer/MAX_VALUE))
  ([s startparse queue-size]
   (let [q (LinkedBlockingQueue. queue-size)
         NIL (Object.) ;nil sentinel since LBQ doesn't support nils
         agt (agent nil)
         s (if (instance? Reader s) (InputSource. s) s)
         step (fn step []
                (lazy-seq
                  (if-let [x (.take q)]
                    (cons x (step))
                    @agt)))  ;will be nil, touch agent just to propagate errors
         keep-alive (WeakReference. step)
         enqueue (fn [x]
                     (if (.get keep-alive)
                       (when-not (.offer q x 1 TimeUnit/SECONDS)
                                 (recur x))
                       (throw (Exception. "abandoned"))))]
     (send-off agt
       (fn [_]
         (try
           (startparse s (proxy [DefaultHandler] []
             (startElement [uri local-name q-name #^Attributes atts]
               ;(prn :start-element q-name)(flush)
               (let [attrs (into {} (for [i (range (.getLength atts))]
                                         [(keyword (.getQName atts i))
                                          (.getValue atts i)]))]
                 (enqueue (struct node :start-element (keyword q-name) attrs))))
             (endElement [uri local-name q-name]
               ;(prn :end-element q-name)(flush)
               (enqueue (struct node :end-element (keyword q-name))))
             (characters [ch start length]
               ;(prn :characters)(flush)
               (let [st (String. ch start length)]
                 (when (seq (.trim st))
                   (enqueue (struct node :characters nil nil st)))))))
           (finally
             (.put q false)))))
     (step))))

Copyright (c) Rich Hickey. All rights reserved.

The use and distribution terms for this software are covered by the Eclipse Public License 1.0, which can be found in the file epl-v10.html at the root of this distribution. By using this software in any fashion, you are agreeing to be bound by the terms of this license. You must not remove this notice, or any other, from this software.