-
Notifications
You must be signed in to change notification settings - Fork 69
/
process.clj
59 lines (54 loc) · 2.05 KB
/
process.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
; Copyright (c) Rich Hickey and contributors. All rights reserved.
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
; which can be found in the file epl-v10.html at the root of this distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.
(ns clojure.data.xml.process
(:require [clojure.data.xml.event :refer [element-nss] :as evt]
[clojure.data.xml.name :as name :refer [gen-prefix *gen-prefix-counter* qname-uri]]
[clojure.data.xml.node :refer [element] :as node]
[clojure.data.xml.tree :refer [flatten-elements] :as tree]
[clojure.string :as str]
[clojure.data.xml.pu-map :as pu]))
(defn- reduce-tree
"Optimized reducer for in-order traversal of nodes, with reduce-like accumulator"
[f init xml]
(loop [result init
{:as tree [child & next-children :as children] :content} xml
[parent & next-parents :as parents] ()]
(if (seq children)
(recur (f result tree)
child
(concat next-children parents))
(if (seq parents)
(recur (f result tree)
parent
next-parents)
(f result tree)))))
(defn- qname-uri-xf [xf]
(fn [s el]
(if (map? el)
(reduce-kv
(fn [s attr _] (xf s (qname-uri attr)))
(xf s (qname-uri (:tag el)))
(:attrs el))
s)))
(defn find-xmlns
"Find all xmlns occuring in a root"
[xml]
(persistent!
(reduce-tree (qname-uri-xf conj!)
(transient #{}) xml)))
(defn aggregate-xmlns
"Put all occurring xmlns into the root"
[xml]
(with-meta
xml {:clojure.data.xml/nss
(binding [*gen-prefix-counter* 0]
(-> (fn [tm uri]
(pu/assoc! tm (gen-prefix) uri))
qname-uri-xf
(reduce-tree (pu/transient pu/EMPTY) xml)
pu/persistent!))}))