KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jimm > util > XMLWriter


1 package jimm.util;
2 import java.awt.Color JavaDoc;
3 import jimm.util.StringUtils;
4 import java.io.PrintWriter JavaDoc;
5 import java.io.Writer JavaDoc;
6 import java.io.OutputStream JavaDoc;
7 import java.util.ArrayList JavaDoc;
8
9 /**
10  * An XML writer is a print writer that knows how to output XML elements
11  * and make the output look pretty.
12  * <p>
13  * Calling <code>indent</code> and <code>outdent</code> changes the
14  * indentation level. The default indentation width is 4 spaces.
15  *
16  * @author Jim Menard, <a HREF="mailto:jimm@io.com">jimm@io.com</a>
17  */

18 public class XMLWriter extends PrintWriter JavaDoc {
19
20 // ================================================================
21
static class ElementInfo {
22 String JavaDoc name;
23 boolean outdentBeforeEnd;
24 ElementInfo(String JavaDoc name) {
25     this.name = name;
26     outdentBeforeEnd = false;
27 }
28 }
29 // ================================================================
30

31 protected static final int DEFAULT_INDENTATION_WIDTH = 4;
32
33 protected int width;
34 protected int level;
35 protected boolean newline;
36 protected ArrayList JavaDoc elementStack;
37 protected boolean inElementStart;
38
39 /**
40  * Constructor, same as the <code>PrintWriter</code> version.
41  *
42  * @param out an output stream
43  */

44 public XMLWriter(OutputStream JavaDoc out) {
45     super(out);
46     init(DEFAULT_INDENTATION_WIDTH);
47 }
48
49 /**
50  * Constructor, same as <code>PrintWriter</code> version without the
51  * <i>width</i> parameter.
52  *
53  * @param out an output stream
54  * @param autoFlush if <code>true</code>, the <code>println()</code> methods
55  * will flush the output bufferset to flush after every line
56  * @param width indentation width in spaces
57  */

58 public XMLWriter(OutputStream JavaDoc out, boolean autoFlush, int width) {
59     super(out, autoFlush);
60     init(width);
61 }
62
63 /**
64  * Constructor, same as the <code>PrintWriter</code> version.
65  *
66  * @param out a writer
67  */

68 public XMLWriter(Writer JavaDoc out) {
69     super(out);
70     init(DEFAULT_INDENTATION_WIDTH);
71 }
72
73 /**
74  * Constructor, same as the <code>PrintWriter</code> version.
75  *
76  * @param out a writer
77  * @param autoFlush if <code>true</code>, the <code>println()</code> methods
78  * will flush the output bufferset to flush after every line
79  * @param width indentation width in spaces
80  */

81 public XMLWriter(Writer JavaDoc out, boolean autoFlush, int width) {
82     super(out, autoFlush);
83     init(width);
84 }
85
86 /**
87  * Initializes some instance variables. Called from constructors.
88  *
89  * @param indentationWidth number of spaces per indentation level
90  */

91 protected void init(int indentationWidth) {
92     width = indentationWidth;
93     level = 0;
94     newline = true;
95     elementStack = new ArrayList JavaDoc();
96     inElementStart = false;
97 }
98
99 /**
100  * Increases the indentation level by one.
101  */

102 public void indent() { ++level; }
103
104 /**
105  * Decreases the indentation level by one.
106  */

107 public void outdent() { if (--level < 0) level = 0; }
108
109 public void print(boolean b) { doIndent(); super.print(b); }
110 public void print(char c) {
111     doIndent();
112     super.print(c);
113     if (c == '\n') newline = true;
114 }
115 public void print(char[] s) {
116     for (int i = 0; i < s.length; ++i) print(s[i]);
117 }
118 public void print(double d) { doIndent(); super.print(d); }
119 public void print(float f) { doIndent(); super.print(f); }
120 public void print(int i) { doIndent(); super.print(i); }
121 public void print(long l) { doIndent(); super.print(l); }
122 public void print(Object JavaDoc obj) { print(obj.toString()); }
123
124 /**
125  * This method does not handle newlines embedded in the string.
126  *
127  * @param str the string to output
128  */

129 public void print(String JavaDoc str) { doIndent(); super.print(str); }
130
131 public void println() {
132     super.println();
133     newline = true;
134 }
135 public void println(boolean b) { doIndent(); super.println(b); }
136 public void println(char c) {
137     doIndent();
138     super.println(c);
139     if (c == '\n') {
140     newline = true;
141     doIndent();
142     newline = true;
143     }
144 }
145 public void println(char[] s) {
146     for (int i = 0; i < s.length; ++i) print(s[i]);
147     println();
148 }
149 public void println(double d) { doIndent(); super.println(d); newline = true; }
150 public void println(float f) { doIndent(); super.println(f); newline = true; }
151 public void println(int i) { doIndent(); super.println(i); newline = true; }
152 public void println(long l) { doIndent(); super.println(l); newline = true; }
153 public void println(Object JavaDoc obj) { println(obj.toString()); }
154 // FIX: this is not correct, but it is not worth fixing right now.
155
// It does not handle newlines embedded in the string, but I do not care.
156
public void println(String JavaDoc str) {
157     doIndent();
158     super.println(str);
159     newline = true;
160 }
161
162 /**
163  * Performs indentation by printing the correct number of tabs and spaces.
164  */

165 protected void doIndent() {
166     if (newline) {
167     int spaces = level * width;
168     while (spaces >= 8) {
169         super.print("\t");
170         spaces -= 8;
171     }
172     super.print(" ".substring(0, spaces));
173     newline = false;
174     }
175 }
176
177 public void xmlDecl(String JavaDoc encoding) {
178     println("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>");
179 }
180
181 /** Writes the end of the start of an element. */
182 protected void finishStartElement(boolean outputNewline) {
183     inElementStart = false;
184     print('>');
185     if (outputNewline) println();
186 }
187
188 /** Writes the end of the start of an element. */
189 protected void finishStartElement() {
190     inElementStart = false;
191     println('>');
192 }
193
194 protected void parentShouldOutdent() {
195     ElementInfo info = (ElementInfo)elementStack.get(elementStack.size() - 1);
196     info.outdentBeforeEnd = true;
197 }
198
199 /**
200  * Starts an element. This may be followed by zero or more calls to
201  * <code>attribute</code>. The start-element will be closed by the first
202  * following call to any method other than attribute.
203  */

204 public void startElement(String JavaDoc name) {
205     if (inElementStart) {
206     finishStartElement();
207     indent();
208     parentShouldOutdent();
209     }
210     elementStack.add(new ElementInfo(name));
211     inElementStart = true;
212     doIndent();
213     print("<" + name);
214 }
215
216 /** Writes an attribute. */
217 public void attr(String JavaDoc name, String JavaDoc value) {
218     print(" " + name + "=\"" + StringUtils.escapeXML(value) + "\"");
219 }
220
221 public void attr(String JavaDoc name, double value) {
222     print(" " + name + "=\"" + value + "\"");
223 }
224
225 public void attr(String JavaDoc name, int value) {
226     print(" " + name + "=\"" + value + "\"");
227 }
228
229 public void attr(String JavaDoc name, char value) {
230     attr(name, "" + value);
231 }
232
233 public void attr(String JavaDoc name, boolean bool) {
234     attr(name, bool ? "true" : "false");
235 }
236
237 public void attr(String JavaDoc name, Color JavaDoc c) {
238     attr(name, "" + c.getRed() + ';' + c.getGreen() + ';' + c.getBlue() + ';'
239      + c.getAlpha());
240 }
241
242 public void attr(String JavaDoc name, Object JavaDoc value) {
243     attr(name, value.toString());
244 }
245
246 /**
247  * Ends an element. This may output an end-tag or close the current
248  * start-tag as an empty element.
249  */

250 public void endElement() {
251     ElementInfo info =
252     (ElementInfo)elementStack.remove(elementStack.size() - 1);
253     if (info.outdentBeforeEnd)
254     outdent();
255
256     if (inElementStart) {
257     inElementStart = false;
258     println("/>");
259     }
260     else {
261     doIndent();
262     println("</" + info.name + ">");
263     }
264 }
265
266 public void cdataElement(String JavaDoc name, String JavaDoc text) {
267     startElement(name);
268     cdata(text);
269     endElement();
270
271 // boolean in = false;
272
// if (inElementStart) {
273
// finishStartElement();
274
// in = true;
275
// }
276
// if (in) indent();
277
// doIndent();
278
// print("<" + name + ">");
279
// cdata(text);
280
// println("</" + name + ">");
281
// if (in) outdent();
282
}
283
284 public void cdata(String JavaDoc text) {
285     if (inElementStart)
286     finishStartElement(false);
287     print("<![CDATA[" + (text == null ? "" : text) + "]]>");
288 }
289
290 public void textElement(String JavaDoc name, String JavaDoc text) {
291     startElement(name);
292     text(text);
293     endElement();
294
295 // boolean in = false;
296
// if (inElementStart) {
297
// finishStartElement();
298
// in = true;
299
// }
300
// if (in) indent();
301
// doIndent();
302
// print("<" + name + ">");
303
// text(text);
304
// println("</" + name + ">");
305
// if (in) outdent();
306
}
307
308 public void text(String JavaDoc text) {
309     if (inElementStart)
310     finishStartElement(false);
311     print(StringUtils.escapeXML(text == null ? "" : text));
312 }
313
314 public void comment(String JavaDoc text) {
315     if (inElementStart)
316     finishStartElement();
317     doIndent();
318     println("<!-- " + text + " -->");
319 }
320
321 }
322
Popular Tags