Skip to content

Commit 6a9b32f

Browse files
committed
Implement #xml/element reader tag
Unfortunately, this necessitates removal of hash caching, because deftypes with mutable fields cannot be compiled: CLJ-2029
1 parent adce289 commit 6a9b32f

4 files changed

Lines changed: 29 additions & 25 deletions

File tree

src/main/clojure/clojure/data/xml/node.cljc

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,6 @@
1717
(java.io Serializable Writer)
1818
(java.util Map))))
1919

20-
#?
21-
(:clj
22-
;; recreate cljs' caching-hash macro
23-
(defmacro caching-hash [this hash-fn hash-field]
24-
`(do (when-not ~hash-field
25-
(set! ~hash-field (~hash-fn ~this)))
26-
~hash-field)))
27-
2820
;; Parsed data format
2921
;; Represents a node of an XML tree
3022

@@ -36,9 +28,9 @@
3628
;; also, elements don't have an extmap and degrade to hash-maps also
3729
;; when assoc'ing unknown keys
3830

39-
(deftype Element [tag attrs content meta
40-
#?(:clj ^:volatile-mutable hash
41-
:cljs ^:mutable hash)]
31+
;; FIXME hash caching cannot be used: http://dev.clojure.org/jira/browse/CLJ-2092
32+
33+
(deftype Element [tag attrs content meta]
4234

4335
;; serializing/cloning, hashing, equality, iteration
4436

@@ -47,14 +39,14 @@
4739
[Serializable
4840
MapEquivalence
4941
IHashEq
50-
(hasheq [this] (caching-hash this APersistentMap/mapHasheq hash))
42+
(hasheq [this] (APersistentMap/mapHasheq this))
5143
Iterable
5244
(iterator [this] (RecordIterator. this [:tag :attrs :content] (RT/iter nil)))]
5345
:cljs
5446
[ICloneable
55-
(-clone [_] (Element. tag attrs content meta hash))
47+
(-clone [_] (Element. tag attrs content meta))
5648
IHash
57-
(-hash [this] (caching-hash this hash-unordered-coll hash))
49+
(-hash [this] (hash-unordered-coll this))
5850
IEquiv
5951
(-equiv [this other] (or (identical? this other)
6052
^boolean (js/cljs.core.equiv_map this other)))
@@ -71,7 +63,7 @@
7163
(concat [">"] content ["</" qname ">"])
7264
["/>"])))))
7365
#?@(:clj
74-
[(hashCode [this] (caching-hash this APersistentMap/mapHash hash))
66+
[(hashCode [this] (APersistentMap/mapHash this))
7567
(equals [this other] (APersistentMap/mapEquals this other))
7668
IPersistentMap
7769
(equiv [this other] (APersistentMap/mapEquals this other))])
@@ -98,9 +90,9 @@
9890
#?(:cljs IAssociative)
9991
(#?(:clj assoc :cljs -assoc) [this k v]
10092
(case k
101-
:tag (Element. v attrs content meta nil)
102-
:attrs (Element. tag v content meta nil)
103-
:content (Element. tag attrs v meta nil)
93+
:tag (Element. v attrs content meta)
94+
:attrs (Element. tag v content meta)
95+
:content (Element. tag attrs v meta)
10496
(with-meta {:tag tag :attrs attrs :content content k v} meta)))
10597
#?(:cljs IMap)
10698
(#?(:clj without :cljs -dissoc) [this k]
@@ -136,7 +128,7 @@
136128
(#?(:clj meta :cljs -meta) [this] meta)
137129
#?(:cljs IWithMeta)
138130
(#?(:clj withMeta :cljs -with-meta) [this next-meta]
139-
(Element. tag attrs content next-meta hash))
131+
(Element. tag attrs content next-meta))
140132

141133
;; cljs printing is protocol-based
142134

@@ -179,18 +171,18 @@
179171
(defn element*
180172
"Create an xml element from a content collection and optional metadata"
181173
([tag attrs content meta]
182-
(Element. tag (or attrs {}) (remove nil? content) meta nil))
174+
(Element. tag (or attrs {}) (remove nil? content) meta))
183175
([tag attrs content]
184-
(Element. tag (or attrs {}) (remove nil? content) nil nil)))
176+
(Element. tag (or attrs {}) (remove nil? content) nil)))
185177

186178
#?(:clj
187179
;; Compiler macro for inlining the two constructors
188180
(alter-meta! #'element* assoc :inline
189181
(fn
190182
([tag attrs content meta]
191-
`(Element. ~tag (or ~attrs {}) (remove nil? ~content) ~meta nil))
183+
`(Element. ~tag (or ~attrs {}) (remove nil? ~content) ~meta))
192184
([tag attrs content]
193-
`(Element. ~tag (or ~attrs {}) (remove nil? ~content) nil nil)))))
185+
`(Element. ~tag (or ~attrs {}) (remove nil? ~content) nil)))))
194186

195187
(defn element
196188
"Create an xml Element from content varargs"
@@ -207,3 +199,12 @@
207199
"Create a Comment node"
208200
[content]
209201
(Comment. content))
202+
203+
(defn map->Element [{:keys [tag attrs content] :as el}]
204+
(element* tag attrs content (meta el)))
205+
206+
(defn tagged-element [el]
207+
(cond (map? el) (map->Element el)
208+
;; TODO support hiccup syntax
209+
:else (throw (ex-info "Unsupported element representation"
210+
{:element el}))))

src/main/clojure/data_readers.clj

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/main/clojure/data_readers.cljc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{xml/ns clojure.data.xml.name/uri-symbol
2+
xml/element clojure.data.xml.node/tagged-element}

src/test/clojure/clojure/data/xml/test_equiv.cljc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
(element :foo) {:tag :foo :attrs {} :content []}
99
(element (qname "DAV:" "foo")) {:tag (qname "DAV:" "foo") :attrs {} :content []}
1010
(element :foo {:a "b"}) {:tag :foo :attrs {:a "b"} :content []}
11-
(element :foo {:a "b"} "a" "b") {:tag :foo :attrs {:a "b"} :content ["a" "b"]}))
11+
(element :foo {:a "b"} "a" "b") {:tag :foo :attrs {:a "b"} :content ["a" "b"]}
12+
#?@(:clj ;; wait for https://github.com/clojure/clojurescript/commit/9484a134bdf039c10ec3c26c8aaa3acd0dcd9875
13+
[#xml/element {:tag :foo :content ["C"]} {:tag :foo :attrs {} :content ["C"]}])))

0 commit comments

Comments
 (0)