    1 - A seq of nodes extracted from the event seq, and
    2 - A seq of the unconsumed events.
   "
-  [events & [xmlns-prefix-map]]
-
-  ;; Notes: I tried for a while to make this consume the event-seq
-  ;;        lazily, but that made my brain explode.
-  
-  (loop [nodes []
-         [[type data :as evt] & events] events
-         ns-stack (list xmlns-prefix-map)]
-    
-    (case type
-      
-      :start-prefix-mapping
-      (let [[_ prefix uri] evt
-            ns-map (assoc-in (peek ns-stack) [:xmlns uri] prefix)]
-        (recur nodes events (conj ns-stack ns-map)))
-
-      :end-prefix-mapping
-      (recur nodes events (pop ns-stack))
-      
-      :start-element
-      (let [[_ tag attrs]     evt
-            [children events] (events->nodes events (peek ns-stack))
-            elt               (Element. tag attrs children nil)]
-        (recur (conj nodes (with-meta elt {:xmlns (peek ns-stack)}))
-               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]
-      
-      )))
+  [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]
-  (let [[nodes events] (events->nodes events)]
+  [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


(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

        ;; <exception>].  This transformation will re-throw them.
        e (throw-on-error e)

        ;; SAX parsers can emit multiple "characters" events for one
        ;; piece of text (for example, when it contains entities, such
        ;; as &amp;). It's generally more convenient to work with
