Skip to content

Instantly share code, notes, and snippets.

@agrison
Last active June 25, 2020 18:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agrison/8ee5bf04668d42ac1bc340cbadb81af9 to your computer and use it in GitHub Desktop.
Save agrison/8ee5bf04668d42ac1bc340cbadb81af9 to your computer and use it in GitHub Desktop.
XSLT + EDN = XDN \o/

XDN

XDN is a Clojure(script) library for transforming EDN to EDN using EDN.

I shouldn't have done that.

Quick Start

Imagine you have this

[{:persons 
  [{:person/username "JS1"
    :person/name "John"
    :person/family-name "Smith"}
   {:person/username "MI1"
    :person/name "Jane"
    :person/family-name "Doe"}]}]

You can turn it to this:

 [:root [{:username "JS1" :full-name "John Smith"}
         {:username "MI1" :full-name "Jane Doe"}]]

With this:

[[:xdn/tpl :persons {:root [:xdn/apply :person]}]
 [:xdn/tpl :person {:username  [:xdn/value :person/username]
                    :full-name (fn [{:person/keys [name family-name]}] (str name " " family-name))}]]

Or you can transform it to this:

 [:html
  [:head [:title "Testing EDN Example"]]
  [:body
   [:h1 "List of persons"]
   [:ul
    [:li [:b "JS1"] " " [:span.full-name "John Smith"]]
    [:li [:b "MI1"] " " [:span.full-name "Jane Doe"]]]]]

With this:

[[:xdn/tpl :persons [:html
                     [:head [:title "Testing EDN Example"]
                      [:body
                       [:h1 "List of persons"]
                       [:ul [:xdn/apply :person]]]]]]
 [:xdn/tpl :person [:li [:b [:xdn/value :person/username]]
                    " " (fn [{:person/keys [name family-name]}] [:span.full-name (str name " " family-name)])]]]

Possibilities

It takes a vector of templates, each template having some kind of id directly linked to the path in the source EDN (:persons which would be like "/persons" in XPATH), or if not using a keyword then it could be a vector of path ala get-in.

What is cool is that it is plain EDN, and you have possibilities to embed functions to do some computations and generate what you want like hiccup or just plain structures. You have access to Clojure if and so on like xsl-if in XSLT.

:xdn/tpl

It represents a template

:xdn/value

It let's take a value from the model which is passed to a template

You can also just use plain functions which takes the map of all the elements in the EDN model as a parameter (namespaced) so that you can just extract what you need to create the final EDN structure to be wrapped in place with the model (applying the template).

:xdn/apply

It applies a template which is retrieved using its id (like :person).

Limitations / Future Work

[ what would you like to have added or changed in your design? ] [ any particular challenges? ] [ was a data-driven approach suitable for this problem? ] [ any of the reflection questions particularly relevant? ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment