 
     event-seq))
 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Transformations of event streams
-(defn throw-if-error [[type ex :as evt]]
-  (if (= :error type)
-    (throw ex)
-    evt))
 
 (defn throw-on-error [events]
-  (map throw-if-error events))
-
-
-;; swiped from data.xml:
-(defn attrs->map [^Attributes atts]
-  (into {} (for [^Long i (range (.getLength atts))]
-             [(keyword (.getQName atts i))
-              (.getValue atts i)])))
-
-(defn mapify-attrs
-  "Tranform start-element events so that attributes are stored in a
-  map, rather than an Attributes instance."
-  [events]
-  (map (fn [[type tag attrs :as evt]]
-         (if (= type :start-element)
-           [:start-element tag (attrs->map attrs)]
+  (map (fn [[type exc :as evt]]
+         (if (= :error type)
+           (throw exc)
            evt))
        events))
+
 
 (defn merge-adjacent-text
   "Transform the event stream so that adjacent bits of text are


(defn sax-seq
  "Given a source of XML, returns a sequence of events, in the form of
  vectors of [type data ...]. See xml-handler for details."
  [in & [opts]]
  (let [{:keys [namespaces]
         :or   {namespaces true}} opts
         
        ^InputSource in (as-input-source in)
        parser          (XMLReaderFactory/createXMLReader)
        [put event-seq] (pipe/pipe)
        handler         (xml-handler put)]
    
    (.setContentHandler parser handler)
    
    ;; Set the "lexical-handler" property in order to get
    ;; start-prefix-mapping & end-prefix-mapping events.
    (.setProperty parser "http://xml.org/sax/properties/lexical-handler" handler)
    
    ;; Setting this to true means that undeclared namespace-prefixes
    ;; will be an error.
    (.setFeature parser "http://xml.org/sax/features/namespaces" namespaces)

    ;; Run the SAX parser in a thread.
    (future

   1 - A seq of nodes extracted from the event seq, and
   2 - A seq of the unconsumed events.
  "
  [events & [opts]]
  ;; TODO - this function is way too busy
  (let [{:keys [namespaces]} opts

        attr-key
        (if namespaces
          (fn [^Attributes attrs ^Long i]
            (let [uri (.getURI attrs i)
                  q-name (.getQName attrs i)]
              (if (.isEmpty uri)
                (keyword q-name)
                (let [[prefix _] (string/split q-name #":" 2)]
                  (with-meta
                    [(keyword (.getLocalName attrs i)) uri]
                    {:prefix prefix})))))
          (fn [^Attributes attrs ^Long i]
            (keyword (.getQName attrs i))))

        attrs->map
        (fn [^Attributes attrs]
          (into {} (for [^Long i (range (.getLength attrs))]
                     [(attr-key attrs i) (.getValue attrs i)])))

        make-element
        (if namespaces
          (fn [[_ uri local-name q-name attrs] content ns-map]
            (let [[prefix tag] (string/split q-name #":" 2)
                  prefix (if tag prefix nil)]
              (with-meta
                (Element. (keyword local-name)
                          (attrs->map attrs)
                          content
                          uri)
                (if prefix
                  (assoc ns-map :prefix prefix) ;TODO - intern this somehow
                  ns-map))))
          (fn [[_ _ _ q-name attrs] content _]
            (Element. (keyword q-name)
                      (attrs->map attrs)
                      content
                      nil)))
        
        make-nodes
        (fn make-nodes [events xmlns-map]
          (loop [nodes []
                 [[type data :as evt] & events] events
                 ns-stack (list xmlns-map)]
            
            (case type
              
              :start-prefix-mapping
              (let [[_ prefix uri] evt
                    ns-map (assoc-in (peek ns-stack) [:xmlns prefix] uri)]
                (recur nodes events (conj ns-stack ns-map)))

              :end-prefix-mapping
              ;; TODO - sanity check? make sure the prefix is in the ns-map?
              (recur nodes events (pop ns-stack))
              
              :start-element
              (let [ns-map (peek ns-stack)
                    [children events] (make-nodes events ns-map)
                    elt (make-element evt children ns-map)]
                (recur (conj nodes elt)
                       events
                       ns-stack))

              :text
              (recur (conj nodes data)
                     events
                     ns-stack)

              :comment
              (recur (conj nodes (Comment. data))
                     events
                     ns-stack)

              :start-cdata
              (let [[text-nodes [end-cdata & events]]
                    (split-with (fn [[type]] (= type :text)) events)]
                (assert (= (end-cdata 0) :end-cdata) "Expected :end-cdata event.")
                (recur (conj nodes (CData. (apply str (map second text-nodes))))
                       events
                       ns-stack))

              :processing-instruction
              (let [[_ target text] evt]
                (recur (conj nodes (PI. target text))
                       events
                       ns-stack))

              (:end-element nil)
              [nodes events]
              
              )))]
    (make-nodes events nil)))

(defn make-tree
  "Takes a seq of SAX events and returns a vector of the top-level nodes."
  [events & [opts]]
  (let [[nodes events] (events->nodes events opts)]
    (when (seq events)
      ;; This shouldn't be possible if the source of the events is an
      ;; actual SAX parser, but could happen for an event-seq from
