Skip to content

Instantly share code, notes, and snippets.

@shapiy
Last active November 4, 2019 11:57
Show Gist options
  • Save shapiy/28c6d0e7625701cccd0421964301f345 to your computer and use it in GitHub Desktop.
Save shapiy/28c6d0e7625701cccd0421964301f345 to your computer and use it in GitHub Desktop.
Implementing XSLT-like transformation in bare Clojure: https://shapiy.github.io/blog/clojure-xslt/
(ns io.shapiy.core
(:gen-class)
(:require [clojure.data.xml :refer :all])
(:import (clojure.data.xml Element)))
(def html "<!DOCTYPE html>
<html>
<body>
<h1>Programming languages</h1>
<p>There are many, for example:</p>
<ol>
<li>Clojure (<a href=\"http://clojure.org\">official site</a>)</li>
<li>XSLT (<a href=\"http://www.w3.org/Style/XSL/\">W3C page</a>)</li>
</ol>
</body>
</html>")
(declare apply-templates)
(declare copy)
(defn map-identity [node] (copy node apply-templates))
(defn apply-templates [node-or-nodes]
(if (seq? node-or-nodes)
(map map-identity node-or-nodes)
(map-identity node-or-nodes)))
(defn copy [node f]
(cond
;; Element?
(.isInstance Element node) [(:tag node)
(f (:attrs node))
(f (:content node))]
;; Attribute map?
(map? node) node
;; Text node?
(string? node) node))
(defn transform []
(-> (parse-str html)
apply-templates
sexp-as-element
indent-str))
(defn -main [] (println (transform)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment