1 package com.bradmcevoy.http;
2
3 import org.apache.commons.io.output.ByteArrayOutputStream;
4 import java.io.FileNotFoundException;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.io.PrintWriter;
9 import java.io.Writer;
10
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import com.bradmcevoy.io.FileUtils;
15
16
17
18
19
20
21
22
23
24 public class XmlWriter {
25
26 private Logger log = LoggerFactory.getLogger(XmlWriter.class);
27
28 public enum Type {
29
30 OPENING,
31 CLOSING,
32 NO_CONTENT
33 };
34 protected final Writer writer;
35
36 public XmlWriter(OutputStream out) {
37 this.writer = new PrintWriter(out, true);
38 }
39
40
41
42
43
44
45 private void append(String value) {
46 try {
47 writer.write(value);
48 } catch (IOException ex) {
49 throw new RuntimeException(ex);
50 }
51 }
52
53
54
55
56
57
58 private void append(char c) {
59 try {
60 writer.write((int) c);
61 } catch (IOException ex) {
62 throw new RuntimeException(ex);
63 }
64 }
65
66
67
68
69
70
71
72
73
74
75 public void writeProperty(String namespace, String namespaceInfo, String name, String value) {
76 writeElement(namespace, namespaceInfo, name, Type.OPENING);
77 append(value);
78 writeElement(namespace, namespaceInfo, name, Type.CLOSING);
79
80 }
81
82 public void writeProperty(String namespace, String name, String value) {
83 if (value == null) {
84 writeProperty(namespace, name);
85 } else {
86 writeElement(namespace, name, Type.OPENING);
87 append(value);
88 writeElement(namespace, name, Type.CLOSING);
89 }
90 }
91
92 public void writeProperty(String namespace, String name) {
93 writeElement(namespace, name, Type.NO_CONTENT);
94 }
95
96 public void writeProperty(String name) {
97 writeElement(null, name, Type.NO_CONTENT);
98 }
99
100
101 public void writeElement(String namespace, String name, Type type) {
102 writeElement(namespace, null, name, type);
103 }
104
105
106
107
108
109
110
111 public void open(String namespace, String name) {
112 writeElement(namespace, name, Type.OPENING);
113 }
114
115
116
117
118
119
120
121 public void close(String namespace, String name) {
122 writeElement(namespace, name, Type.CLOSING);
123 }
124
125
126
127
128
129
130 public void open(String name) {
131 writeElement(null, name, Type.OPENING);
132 }
133
134
135
136
137
138
139 public void close(String name) {
140 writeElement(null, name, Type.CLOSING);
141 }
142
143
144
145
146
147 public class Element {
148
149 private final Element parent;
150 private final String nsPrefix;
151 private final String name;
152 private boolean openEnded;
153
154
155
156
157
158
159
160
161 Element(Element parent, String name) {
162 this(parent, null, name);
163 }
164
165
166
167
168
169
170
171
172
173 Element(Element parent, String nsPrefix, String name) {
174 this.parent = parent;
175 this.name = name;
176 this.nsPrefix = nsPrefix;
177 append("<");
178 if (nsPrefix != null) {
179 append(nsPrefix);
180 append(":");
181 }
182 append(name);
183 }
184
185
186
187
188
189
190
191
192 public Element writeAtt(String name, String value) {
193 append(" ");
194 append(name);
195 append("=");
196 append((char) 34);
197 append(value == null ? "" : value);
198 append((char) 34);
199 return this;
200 }
201
202
203
204
205
206
207
208 public Element writeText(String text) {
209 return writeText(text, true);
210 }
211
212 public Element writeText(String text, boolean newline) {
213 if (!openEnded) {
214 open(newline);
215 }
216 append(text);
217 return this;
218 }
219
220
221
222
223
224
225
226
227
228 public Element open() {
229 return open(true);
230 }
231
232 public Element open(boolean newline) {
233 openEnded = true;
234 append(">");
235 if (newline) {
236 append("\n");
237 }
238 return this;
239 }
240
241
242
243
244
245
246
247 public Element close() {
248 return close(false);
249 }
250 public Element close(boolean newline) {
251 if (openEnded) {
252 if (nsPrefix != null) {
253 append("</" + nsPrefix + ":" + name + ">\n");
254 } else {
255 append("</" + name + ">\n");
256 }
257 if (newline) {
258 append("\n");
259 }
260 return parent;
261 } else {
262 if (newline) {
263 append("\n");
264 }
265 return noContent();
266 }
267 }
268
269
270
271
272
273
274 public Element noContent() {
275 append("/>\n");
276 return parent;
277 }
278 public Element noContent(boolean newLine) {
279 append("/>");
280 if(newLine) {
281 append("\n");
282 }
283 return parent;
284 }
285
286
287
288
289
290
291
292 public Element begin(String name) {
293 return begin(null, name);
294 }
295
296 public Element begin(String prefix, String name) {
297 if (!openEnded) {
298 open();
299 }
300
301 Element el = new Element(this, prefix, name);
302 return el;
303 }
304
305
306
307
308
309
310
311
312
313 public Element prop(String name, String value) {
314 begin(name).writeText(value,false).close(true);
315 return this;
316 }
317
318 public Element prop(String name, Integer value) {
319 if (value != null) {
320 prop(name, value.toString());
321 } else {
322 begin(name).noContent();
323 }
324 return this;
325 }
326 }
327
328 public Element begin(String name) {
329 Element el = new Element(null, name);
330 return el;
331 }
332
333 public Element begin(String nsPrefix, String name) {
334 Element el = new Element(null, nsPrefix, name);
335 return el;
336 }
337
338 public void writeElement(String nsPrefix, String nsUrl, String name, Type type) {
339 if ((nsPrefix != null) && (nsPrefix.length() > 0)) {
340 switch (type) {
341 case OPENING:
342 if (nsUrl != null) {
343 append("<" + nsPrefix + ":" + name + " xmlns:" + nsPrefix + "=\"" + nsUrl + "\">");
344 } else {
345 append("<" + nsPrefix + ":" + name + ">");
346 }
347 break;
348 case CLOSING:
349 append("</" + nsPrefix + ":" + name + ">\n");
350 break;
351 case NO_CONTENT:
352 default:
353 if (nsUrl != null) {
354 append("<" + nsPrefix + ":" + name + " xmlns:" + nsPrefix + "=\"" + nsUrl + "\"/>");
355 } else {
356 append("<" + nsPrefix + ":" + name + "/>");
357 }
358 break;
359 }
360 } else {
361 switch (type) {
362 case OPENING:
363 append("<" + name + ">");
364 break;
365 case CLOSING:
366 append("</" + name + ">\n");
367 break;
368 case NO_CONTENT:
369 default:
370 append("<" + name + "/>");
371 break;
372 }
373 }
374 }
375
376
377
378
379
380
381 public void writeText(String text) {
382 append(text);
383 }
384
385
386
387
388
389
390 public void writeData(String data) {
391 append("<![CDATA[" + data + "]]>");
392 }
393
394 public void writeXMLHeader() {
395 append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
396 }
397
398
399
400
401 public void flush() {
402 try {
403 writer.flush();
404 } catch (IOException ex) {
405 throw new RuntimeException(ex);
406 }
407 }
408
409 public void sample(InputStream in) {
410 log.debug("outputting sample");
411 try {
412 ByteArrayOutputStream out = FileUtils.readIn(in);
413 writer.write(out.toString());
414 } catch (FileNotFoundException ex) {
415 log.error("", ex);
416 } catch (IOException ex) {
417 log.error("", ex);
418 } finally {
419 FileUtils.close(in);
420 }
421 }
422
423 public void newLine() {
424 append("\n");
425 }
426 }