Skip to content
/ Eximia Public

A fast and small XML processor for Clojure. With XML namespace support and secure defaults.

License

Notifications You must be signed in to change notification settings

nilern/Eximia

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

95 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Eximia

Clojars Project cljdoc badge Build Status

Eximia Cum Laude Approbatur or just E is the second highest grade in the Finnish Matriculation Exam. It was split off from the highest Laudatur grade in 1996.

A fast and small XML processor for Clojure. With XML namespace support and secure defaults.

Fast

  • About 4x faster than data.xml (0.0.8) or clojure.xml (Clojure 1.10.3) on read
  • About 3-4x faster than data.xml and about 7x faster than clojure.xml on write

Small

One 300 SLOC namespace.

Basic Usage

The requires required for these examples:

> (require '[eximia.core :as exml] '[clojure.java.io :as io])

Reading

> (with-open [input (io/input-stream "dev-resources/hello.xml")]
    (exml/read input))
;=> #eximia.core.Element{:tag #qname[greeting], :attrs {#qname[style] "programmatic"}, :content ["Hello, world!"]}

;; Reader works too (but can be slightly slower):
> (with-open [input (io/reader "dev-resources/hello.xml")]
    (exml/read input))
;=> #eximia.core.Element{:tag #qname[greeting], :attrs {#qname[style] "programmatic"}, :content ["Hello, world!"]}

;; Even slower, just to demonstrate `read-str`:
> (exml/read-str (slurp "dev-resources/hello.xml"))
;=> #eximia.core.Element{:tag #qname[greeting], :attrs {#qname[style] "programmatic"}, :content ["Hello, world!"]}

;; javax.xml.namespace.QName:s are used by default, to support XML namespaces.
;; But keywords can be obtained instead:
> (with-open [input (io/input-stream "dev-resources/hello.xml")]
    (exml/read input {:tag-fn exml/qname->keyword, :key-fn exml/qname->keyword}))
;=> #eximia.core.Element{:tag :greeting, :attrs {:style "programmatic"}, :content ["Hello, world!"]}

Writing

> (def tree (exml/->Element (exml/qname "greeting") {(exml/qname "style") "programmatic"} ["Hello, world!"]))

> (exml/write tree System/out)
; prints <?xml version="1.0" ?><greeting xmlns="" style="programmatic">Hello, world!</greeting>
;=> nil

;; Writer works too (but can be slightly slower)
> (exml/write tree *out*)
; prints <?xml version="1.0" ?><greeting xmlns="" style="programmatic">Hello, world!</greeting>
;=> nil

;; `write-str` is also available:
> (exml/write-str tree)
;=> "<?xml version=\"1.0\" ?><greeting xmlns=\"\" style=\"programmatic\">Hello, world!</greeting>"

;; QName:s are used by default, to support XML namespaces. But keywords can be converted on write.
;; Also while a compact Element record type is provided, any map with the right keys works:
> (def tree* {:tag :greeting, :attrs {:style "programmatic"}, :content ["Hello, world!"]})
> (exml/write tree* System/out {:tag-fn exml/keyword->qname, :key-fn exml/keyword->qname})
; prints <?xml version="1.0" ?><greeting xmlns="" style="programmatic">Hello, world!</greeting>
;=> nil

Tip: Non-Standard StAX Implementations

Eximia is built on the standard Java StAX cursor API and the JRE ships with an implementation of that. But you might want to look at third-party StAX implementations such as Woodstox which has both more features (e.g. IS_VALIDATING) and better performance. Aalto should be even faster. Although the performance differences might be swamped by all the persistent tree allocations Eximia has to do...

About

A fast and small XML processor for Clojure. With XML namespace support and secure defaults.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project