0
# Data Format Processing
1
2
Utilities for processing structured data formats including EDN (Extensible Data Notation), UUID handling, and XML parsing through specialized namespaces: clojure.edn for EDN format reading, clojure.uuid for UUID data readers, and clojure.xml for XML processing.
3
4
## Capabilities
5
6
### EDN Format Reading (clojure.edn)
7
8
Reading and parsing EDN (Extensible Data Notation) format data - a subset of Clojure data structures.
9
10
```clojure { .api }
11
(clojure.edn/read)
12
(clojure.edn/read stream)
13
(clojure.edn/read opts stream)
14
;; Reads next object from stream (PushbackReader), defaults to *in*
15
;; opts: map with optional keys:
16
;; :eof - value to return on end-of-file (default: throws exception)
17
;; :readers - map of tag symbols to data-reader functions
18
;; :default - function of two args called when no reader found for tag
19
;; Returns: parsed EDN data structure
20
21
(clojure.edn/read-string s)
22
(clojure.edn/read-string opts s)
23
;; Reads one object from string s, returns nil when s is nil/empty
24
;; s: EDN string to parse
25
;; opts: map as per clojure.edn/read
26
;; Returns: parsed EDN data structure or nil
27
```
28
29
### UUID Data Readers (clojure.uuid)
30
31
UUID literal syntax support and print methods for java.util.UUID objects.
32
33
```clojure { .api }
34
;; UUID literal syntax
35
#uuid "550e8400-e29b-41d4-a716-446655440000"
36
;; Creates java.util.UUID instance from string representation
37
;; Returns: java.util.UUID
38
39
;; Print methods (automatically available)
40
;; print-method for java.util.UUID outputs #uuid "uuid-string"
41
;; print-dup for java.util.UUID outputs #uuid "uuid-string"
42
```
43
44
### XML Processing (clojure.xml)
45
46
XML parsing and emission functionality for working with XML documents.
47
48
#### XML Data Structure
49
50
XML documents are represented as nested maps with standard keys:
51
52
```clojure { .api }
53
;; XML Element Structure
54
{:tag :element-name
55
:attrs {:attr-name "attr-value" ...} ; nil if no attributes
56
:content [child-elements-and-text...]} ; nil if no content
57
58
;; Accessor functions
59
(clojure.xml/tag element)
60
;; Returns the tag (keyword) of XML element
61
;; Returns: keyword
62
63
(clojure.xml/attrs element)
64
;; Returns the attributes map of XML element
65
;; Returns: map of keyword->string or nil
66
67
(clojure.xml/content element)
68
;; Returns the content vector of XML element
69
;; Returns: vector of child elements and text or nil
70
```
71
72
#### XML Parsing
73
74
```clojure { .api }
75
(clojure.xml/parse source)
76
;; Parses XML from various source types
77
;; source: File, InputStream, Reader, URI, URL, or String filename
78
;; Returns: parsed XML as nested element maps
79
80
(clojure.xml/sax-parser)
81
;; Creates new SAX parser instance
82
;; Returns: javax.xml.parsers.SAXParser
83
84
(clojure.xml/startparse-sax source content-handler)
85
;; Low-level SAX parsing with custom content handler
86
;; source: XML source
87
;; content-handler: SAX ContentHandler implementation
88
;; Returns: nil (handler processes events)
89
90
(clojure.xml/startparse-sax-safe source content-handler)
91
;; Safe SAX parsing with external entity processing disabled
92
;; source: XML source
93
;; content-handler: SAX ContentHandler implementation
94
;; Returns: nil
95
```
96
97
#### XML Security
98
99
```clojure { .api }
100
(clojure.xml/disable-external-entities parser)
101
;; Configures SAX parser to disable external entity processing for security
102
;; parser: SAXParser instance
103
;; Returns: configured parser
104
```
105
106
#### XML Emission
107
108
```clojure { .api }
109
(clojure.xml/emit element)
110
;; Prints XML element to *out* in XML format
111
;; element: XML element map
112
;; Returns: nil (prints to *out*)
113
114
(clojure.xml/emit-element element)
115
;; Internal function for emitting XML element structure
116
;; element: XML element map
117
;; Returns: nil (prints to *out*)
118
```
119
120
**Usage Examples:**
121
122
```clojure
123
;; EDN reading examples
124
(require '[clojure.edn :as edn])
125
126
;; Basic EDN parsing
127
(edn/read-string "{:name \"John\" :age 30}")
128
;; => {:name "John", :age 30}
129
130
(edn/read-string "[1 2 3 #{:a :b}]")
131
;; => [1 2 3 #{:a :b}]
132
133
;; EDN with custom readers
134
(edn/read-string
135
{:readers {'date #(java.util.Date. %)}}
136
"#date 1672531200000")
137
;; => #inst "2023-01-01T00:00:00.000-00:00"
138
139
;; Reading from stream
140
(with-open [reader (java.io.PushbackReader.
141
(java.io.StringReader. "{:a 1 :b 2}"))]
142
(edn/read reader))
143
;; => {:a 1, :b 2}
144
145
;; Handle EOF gracefully
146
(edn/read-string {:eof :done} "")
147
;; => :done
148
149
;; UUID examples
150
(require '[clojure.uuid])
151
152
;; Create UUID from literal
153
#uuid "550e8400-e29b-41d4-a716-446655440000"
154
;; => #uuid "550e8400-e29b-41d4-a716-446655440000"
155
156
;; UUID in data structures
157
(def user-data {:id #uuid "550e8400-e29b-41d4-a716-446655440000"
158
:name "Alice"})
159
160
;; UUID printing
161
(str #uuid "550e8400-e29b-41d4-a716-446655440000")
162
;; => "550e8400-e29b-41d4-a716-446655440000"
163
164
(pr-str #uuid "550e8400-e29b-41d4-a716-446655440000")
165
;; => "#uuid \"550e8400-e29b-41d4-a716-446655440000\""
166
167
;; XML processing examples
168
(require '[clojure.xml :as xml])
169
170
;; Parse XML string
171
(def xml-str "<book id='123'>
172
<title>Clojure Programming</title>
173
<author>Rich Hickey</author>
174
<pages>400</pages>
175
</book>")
176
177
;; Note: parse expects file/stream, for strings use:
178
(def book-xml
179
(xml/parse (java.io.ByteArrayInputStream. (.getBytes xml-str))))
180
181
;; Access parsed structure
182
(xml/tag book-xml) ; => :book
183
(xml/attrs book-xml) ; => {:id "123"}
184
(xml/content book-xml) ; => [{:tag :title, :content ["Clojure Programming"]} ...]
185
186
;; Extract specific data
187
(defn get-text [element]
188
(when element
189
(first (xml/content element))))
190
191
(defn find-element [tag elements]
192
(first (filter #(= (xml/tag %) tag) elements)))
193
194
(let [children (xml/content book-xml)]
195
{:title (get-text (find-element :title children))
196
:author (get-text (find-element :author children))
197
:pages (get-text (find-element :pages children))})
198
;; => {:title "Clojure Programming", :author "Rich Hickey", :pages "400"}
199
200
;; Emit XML (prints to *out*)
201
(xml/emit {:tag :person
202
:attrs {:id "1"}
203
:content [{:tag :name :content ["John Doe"]}
204
{:tag :age :content ["30"]}]})
205
;; Prints: <person id='1'><name>John Doe</name><age>30</age></person>
206
207
;; Safe XML parsing (recommended for untrusted input)
208
(defn safe-parse-xml [source]
209
(let [parser (xml/sax-parser)]
210
(xml/disable-external-entities parser)
211
(xml/startparse-sax-safe source xml/content-handler)))
212
213
;; Working with XML files
214
(xml/parse "data.xml") ; parse from file
215
(xml/parse (clojure.java.io/input-stream "http://example.com/data.xml")) ; from URL
216
217
;; Complex XML processing with zipper
218
(require '[clojure.xml :as xml]
219
'[clojure.zip :as zip])
220
221
(defn xml-zip [root]
222
(zip/zipper
223
#(and (map? %) (xml/content %))
224
xml/content
225
(fn [node children]
226
(assoc node :content (vec children)))
227
root))
228
229
;; Navigate XML with zipper
230
(let [xml-data (xml/parse "books.xml")
231
z (xml-zip xml-data)]
232
; Navigate and transform XML using zipper functions
233
)
234
```