Last active
November 4, 2019 11:57
-
-
Save shapiy/b8ccb847382d53bbd9e9f45aefb0ebba to your computer and use it in GitHub Desktop.
Implementing XSLT-like transformation in bare Clojure: https://shapiy.github.io/blog/clojure-xslt/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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 copy) | |
(declare apply-templates) | |
(defn element? [node] (.isInstance Element node)) | |
(defn attrs? [node] (and (map? node) (not (element? node)))) | |
(defn text? [node] (string? node)) | |
(defn map-attrs [attrs] | |
(if (contains? attrs :href) | |
(let [https-url (clojure.string/replace (:href attrs) #"http://" "https://")] | |
(assoc attrs :href https-url)) | |
attrs)) | |
(defn map-identity [node] (copy node apply-templates)) | |
(defn stylesheet [node] | |
(condp #(%1 %2) node | |
element? map-identity | |
attrs? map-attrs | |
text? map-identity)) | |
(defn apply-template [node] | |
(let [template (stylesheet node)] | |
(template node))) | |
(defn apply-templates [node-or-nodes] | |
(if (seq? node-or-nodes) | |
(map apply-template node-or-nodes) | |
(apply-template node-or-nodes))) | |
(defn copy [node f] | |
(cond | |
(element? node) [(:tag node) | |
(f (:attrs node)) | |
(f (:content node))] | |
(attrs? node) node | |
(text? 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