Skip to content

Latest commit

 

History

History
187 lines (130 loc) · 6.15 KB

arr-xml.org

File metadata and controls

187 lines (130 loc) · 6.15 KB

ARR-XML

Overview

This is an arrowized, mostly lazy, xml package following the clojure.data.xml representation. [:tag [:tag1 {:attr1 “hello”} “content”]]

which is delivered as a seq through the arrow chain.

There is heavy reliance on the accumulators and filters of arrows-extra

(use 'conduit.core 'arrows.core 'arrows-extra.core 'clojure.data.xml)

The library allows constructs such as:

(a-comp (arr-select-elem “tag1”) (a-all (a-comp (arr-select-elem “tag2”) arr-characters) (a-comp (arr-select-elem “tag3”) arr-attributes) ) )

The parsers

The parser is lazy, and outputs the clojure.data.xml representation.

(def-arr arr-stream-to-xml-seq [instream]
  ":: InputStream -> [XML]"
  (source-seq instream :coalescing false)

)

Handlers for xml-seq

First, we switch by tag name - pass-through until the tag is encountered. Then send subtags down the channel. We implement this with arr-toggle-switch-inclusive

arr-switch-elem

(defn arr-switch-elem [default-channel name channel & more]
 (arr-toggle-switch-inclusive (if (empty? more) default-channel (apply (partial arr-switch-elem default-channel) more)) (fn[input] (and (= (:name input) name) (= (:type input) :start-element)))
                                           (fn[input] (and (= (:name input) name) (= (:type input) :end-element)))
                                           channel
 )
)

Test

(conduit-map (a-comp arr-stream-to-xml-seq (disperse (arr-switch-elem pass-through :there (a-arr (fn [input] (str "ch1" input)))))) [(java.io.StringReader. "<hello><there><this>is</this></there><your><friendly>newsagent</friendly></your></hello>")])

arr-select-elem

Here we switch into a nil. The reason we don’t switch into a block is so that we can use this with a-all. This means that non matching elements fire as a nil

(defn arr-select-elem [name]
   (arr-switch-elem (a-arr (fn [input] nil)) name pass-through)
  )

arr-select-path

Recursive Use: (arr-select-path :first :second :third) returns <third>

(defn arr-select-path [name & more]
 (a-comp (arr-select-elem name) (if (empty? more) pass-through (apply arr-select-path more)))
)

Test:

(doall (conduit-map (a-comp arr-stream-to-xml-seq (disperse (arr-select-path  :there :this))) [(java.io.StringReader. "<hello><nice>one</nice><there><this>is</this></there><your><friendly>newsagent</friendly></your></hello>")]))

arr-attributes

Select out the attributes map from start elements

(def-proc arr-attributes [input]
  (let [attrs (:attrs input)]
    (if attrs [attrs] [])
    )
  )

arr-characters

Fire a seq of characters from the seq of xml

(def-proc arr-characters [input]

  (let [chars (:str input)]
    (if chars [chars] [])
    )
  )

The tangle

(ns arr-xml.core)
<<use-conduit>>
<<arr-switch-elem>>
<<arr-select-elem>>
<<arr-select-path>>
<<arr-attributes>>
<<arr-characters>>
<<arr-parsers>>
(defproject exchange "1.0.0"
  :description "See arr-xml.org"
  :dependencies [[org.clojure/clojure "1.4.0"]
                 
                 [net.intensivesystems/conduit "0.8.1"]
                 
                 [arrows-extra "1.0.0"]
                 [org.clojure/data.xml "0.0.6"]
                 ])