Skip to content

Instantly share code, notes, and snippets.

@olivergeorge
Last active March 8, 2019 05:18
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 olivergeorge/295d028ec75c4b846da8641f52ebf41f to your computer and use it in GitHub Desktop.
Save olivergeorge/295d028ec75c4b846da8641f52ebf41f to your computer and use it in GitHub Desktop.
(ns xml-to-datascript-roundtrip
(:require [clojure.xml :as xml]
[clojure.java.io :as io]
[datascript.core :as d]))
(def element1 (xml/parse (io/file (io/resource "example.xml"))))
(let [*counter (atom 0)]
(defn genid []
(swap! *counter dec)))
(defn element-txdata
[{:keys [db/id content tag attrs]}]
(let [content (mapv #(cond
(map? %) (assoc % :db/id (genid))
(string? %) {:db/id (genid) :xml/cdata %})
content)]
(lazy-cat
[(assoc attrs
:db/id id
:xml/tag tag
:xml/content (map :db/id content))]
(mapcat element-txdata (remove :xml/cdata content))
(filter :xml/cdata content))))
(def schema
{:xml/content {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many}})
(def db (-> (d/empty-db schema)
(d/db-with (element-txdata element1))))
(defn eid->xml
[id]
(let [{:keys [xml/tag xml/content xml/cdata] :as e} (d/pull db '[* {:xml/content [:xml/tag :xml/cdata :db/id]}] id)
attrs (dissoc e :xml/tag :xml/content :db/id)]
(if cdata
cdata
{:tag tag
:attrs (when-not (empty? attrs) attrs)
:content (when content
(mapv
(fn [c]
(cond (:xml/tag c) (eid->xml (:db/id c))
(:xml/cdata c) (:xml/cdata c)))
content))})))
(comment
(def element1' (eid->xml 1))
(= element1 element1')
(clojure.pprint/pprint element1)
(clojure.pprint/pprint element1')
(clojure.data/diff element1 element1')
(count (d/datoms db :eavt)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment