Skip to content

Commit e48b651

Browse files
committed
DXML-25 emit empty elements
1 parent e7d7dee commit e48b651

4 files changed

Lines changed: 45 additions & 24 deletions

File tree

src/main/clojure/clojure/data/xml/event.clj

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
; Represents a parse event.
3333
(defrecord StartElementEvent [tag attrs nss location-info])
34+
(defrecord EmptyElementEvent [tag attrs nss location-info])
3435
(defrecord CharsEvent [str])
3536
(defrecord CDataEvent [str])
3637
(defrecord CommentEvent [str])
@@ -45,19 +46,22 @@
4546

4647
(let [second-arg #(do %2)
4748
elem-event-generation
48-
{:gen-event (fn elem-gen-event [{:keys [tag attrs] :as element}]
49+
{:gen-event (fn elem-gen-event [{:keys [tag attrs content] :as element}]
4950
(separate-xmlns
50-
attrs #(->StartElementEvent
51+
attrs #((if (seq content)
52+
->StartElementEvent ->EmptyElementEvent)
5153
tag %1 (merge-nss (element-nss* element) %2) nil)))
5254
:next-events (fn elem-next-events [{:keys [tag content]} next-items]
53-
(list* content end-element-event next-items))}
55+
(if (seq content)
56+
(list* content end-element-event next-items)
57+
next-items))}
5458
string-event-generation {:gen-event (comp ->CharsEvent #'xml-str)
5559
:next-events second-arg}
5660
qname-event-generation {:gen-event ->QNameEvent
5761
:next-events second-arg}]
5862
(extend-protocol-fns
5963
EventGeneration
60-
(StartElementEvent EndElementEvent CharsEvent CDataEvent CommentEvent)
64+
(StartElementEvent EmptyElementEvent EndElementEvent CharsEvent CDataEvent CommentEvent)
6165
{:gen-event identity
6266
:next-events second-arg}
6367
(String Boolean Number (Class/forName "[B") Date URI URL nil)
@@ -89,7 +93,8 @@
8993
;; Node Generation for events
9094

9195
(defn event-element [event contents]
92-
(when (instance? StartElementEvent event)
96+
(when (or (instance? StartElementEvent event)
97+
(instance? EmptyElementEvent event))
9398
(element* (:tag event) (:attrs event) contents
9499
(if-let [loc (:location-info event)]
95100
{:clojure.data.xml/location-info loc

src/main/clojure/clojure/data/xml/jvm/emit.clj

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
(javax.xml.stream XMLStreamWriter XMLOutputFactory)
2424
(javax.xml.transform OutputKeys Transformer
2525
TransformerFactory)
26-
(clojure.data.xml.event StartElementEvent EndElementEvent CharsEvent CDataEvent CommentEvent QNameEvent)
26+
(clojure.data.xml.event StartElementEvent EmptyElementEvent EndElementEvent CharsEvent CDataEvent CommentEvent QNameEvent)
2727
(clojure.lang BigInt)
2828
(java.net URI URL)
2929
(java.util Date)
@@ -112,17 +112,24 @@
112112
tpu)]
113113
(pu/persistent! tpu)))
114114

115-
(defn- emit-start-tag [{:keys [attrs nss tag]} ^XMLStreamWriter writer prefix-uri-stack]
115+
(defn- emit-start-tag [{:keys [attrs nss tag]} ^XMLStreamWriter writer prefix-uri-stack empty]
116116
(let [uri (qname-uri tag)
117117
local (qname-local tag)
118118
parent-pu (first prefix-uri-stack)
119119
pu (compute-pu parent-pu nss (map qname-uri (keys attrs)) uri local)]
120-
(if (str/blank? uri)
121-
(.writeStartElement writer local)
122-
(.writeStartElement writer (pu/get-prefix pu uri) local uri))
123-
(emit-ns-attrs writer parent-pu pu)
124-
(emit-attrs writer pu attrs)
125-
(cons pu prefix-uri-stack)))
120+
(if empty
121+
(do (if (str/blank? uri)
122+
(.writeEmptyElement writer local)
123+
(.writeEmptyElement writer (pu/get-prefix pu uri) local uri))
124+
(emit-ns-attrs writer parent-pu pu)
125+
(emit-attrs writer pu attrs)
126+
prefix-uri-stack)
127+
(do (if (str/blank? uri)
128+
(.writeStartElement writer local)
129+
(.writeStartElement writer (pu/get-prefix pu uri) local uri))
130+
(emit-ns-attrs writer parent-pu pu)
131+
(emit-attrs writer pu attrs)
132+
(cons pu prefix-uri-stack)))))
126133

127134
(defn- emit-cdata [^String cdata-str ^XMLStreamWriter writer]
128135
(when-not (str/blank? cdata-str)
@@ -135,7 +142,9 @@
135142

136143
(extend-protocol EventEmit
137144
StartElementEvent
138-
(emit-event [ev writer pu-stack] (emit-start-tag ev writer pu-stack))
145+
(emit-event [ev writer pu-stack] (emit-start-tag ev writer pu-stack false))
146+
EmptyElementEvent
147+
(emit-event [ev writer pu-stack] (emit-start-tag ev writer pu-stack true))
139148
EndElementEvent
140149
(emit-event [ev writer pu-stack]
141150
(assert (next pu-stack) "balanced tags")

src/main/clojure/clojure/data/xml/jvm/parse.clj

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@
99
(ns clojure.data.xml.jvm.parse
1010
(:require [clojure.string :as str]
1111
[clojure.data.xml.event :refer
12-
[->StartElementEvent ->EndElementEvent
12+
[->StartElementEvent ->EmptyElementEvent ->EndElementEvent
1313
->CharsEvent ->CDataEvent ->CommentEvent]]
1414
[clojure.data.xml.impl :refer
1515
[static-case]]
1616
[clojure.data.xml.name :refer
1717
[qname]])
1818
(:import
1919
(javax.xml.stream
20-
XMLInputFactory XMLStreamReader XMLStreamConstants)))
20+
XMLInputFactory XMLStreamReader XMLStreamConstants)
21+
(clojure.data.xml.event EndElementEvent)))
2122

2223
(def ^{:private true} input-factory-props
2324
{:allocator XMLInputFactory/ALLOCATOR
@@ -76,14 +77,16 @@
7677
(.next sreader)
7778
XMLStreamConstants/START_ELEMENT
7879
(if (include-node? :element)
79-
(let [ns-env (nss-hash sreader (or (first ns-envs) {}))]
80-
(cons (->StartElementEvent (qname (.getNamespaceURI sreader)
81-
(.getLocalName sreader)
82-
(.getPrefix sreader))
83-
(attr-hash sreader)
84-
ns-env
85-
location)
86-
(pull-seq sreader opts (cons ns-env ns-envs))))
80+
(let [ns-env (nss-hash sreader (or (first ns-envs) {}))
81+
tag (qname (.getNamespaceURI sreader)
82+
(.getLocalName sreader)
83+
(.getPrefix sreader))
84+
attrs (attr-hash sreader)
85+
next-events (pull-seq sreader opts (cons ns-env ns-envs))]
86+
;; Can't emit EmptyElementEvent here, since
87+
;; for seq-tree node and exit? are mutually exclusive
88+
(cons (->StartElementEvent tag attrs ns-env location)
89+
next-events))
8790
(recur))
8891
XMLStreamConstants/END_ELEMENT
8992
(if (include-node? :element)

src/test/clojure/clojure/data/xml/test_emit.clj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,7 @@
218218
(is (= {:xmlns "NS"}
219219
(nss-meta (parse-str "<foo xmlns=\"NS\"/>"))
220220
(nss-meta (parse-str (emit-str (parse-str "<foo xmlns=\"NS\"/>"))))))))
221+
222+
(deftest test-empty-elements
223+
(is (= (emit-str {:tag :a :content []}) "<?xml version=\"1.0\" encoding=\"UTF-8\"?><a/>"))
224+
(is (= (emit-str {:tag :a :content [""]}) "<?xml version=\"1.0\" encoding=\"UTF-8\"?><a></a>")))

0 commit comments

Comments
 (0)