1
2
3
4
5
6
7
8
9 package org.astrogrid.io.xml;
10
11 import java.io.IOException;
12 import java.io.OutputStream;
13 import java.io.OutputStreamWriter;
14 import java.io.PrintWriter;
15 import java.io.Writer;
16
17 /***
18 * A special XmlTagPrinter used to represent the underlying output stream.
19 * <p>
20 *
21 */
22
23 public class XmlPrinter extends XmlTagPrinter
24 {
25 private PrintWriter out = null;
26
27 private String indentSpaces = " ";
28 private final static int INDENT_SIZE = 3;
29
30 /*** marker to say whether root tag has already been opened. Can only have
31 * one root tag.*/
32 private boolean startedRootTag = false;
33
34 /***
35 * Constructor - pass in output stream to pipe to, and
36 * the initial header will be written if the flag is true.
37 */
38 public XmlPrinter(Writer aWriter, boolean writeProcInstHdr) throws IOException
39 {
40 super(null, null, null);
41 out = new PrintWriter(aWriter);
42 open(writeProcInstHdr);
43 }
44
45 /***
46 * Constructor - pass in output stream to pipe to, and
47 * the initial header will be written
48 */
49 public XmlPrinter(OutputStream out, boolean writeProcInstHdr) throws IOException
50 {
51 this(new OutputStreamWriter(out), writeProcInstHdr);
52 }
53
54
55 protected void open(boolean writeProcInstHdr) throws IOException{
56 if (writeProcInstHdr) {
57 writeLine(0,"<?xml version=\"1.0\"?>");
58 }
59 }
60
61 /***
62 * Should only be able to write comment tags at the root level (ie, at
63 * outputstream level) before any child tags are added
64 *
65 public void writeCommentTag(String tag) throws IOException
66 {
67 Log.affirm(state == STATE_PRETAG, "Cannot write comment "+tag+" as tag "+getChild()+" is set");
68 // Log.assert( (tag.charAt(0) != '!') && (tag.charAt(0) != '?'), "Can only write comments (! or ?) before root tag, not '"+tag+"'");
69 writeLine("<"+tag+">");
70 }
71 /**/
72
73 /***
74 * newTag overridden to ensure only one tag can be set
75 */
76 public XmlTagPrinter newTag(XmlTagPrinter aTag) throws IOException
77 {
78 assert !startedRootTag : "Cannot have more than one tag at root, trying to add "+aTag;
79 startedRootTag = true;
80 return super.newTag(aTag);
81 }
82
83 /***
84 * writeString implementation - writes to the 'output stream' given in
85 * the constructor, using the AsciiOutputStream as a filter.
86 * NB - all writing is eventually channelled through this.
87 */
88 protected void writeString(String s) throws IOException
89 {
90 out.write(s);
91 }
92
93 /***
94 * Implements the XmlOutput.writeIndentedLine method that writes a string
95 * plus a new line character, with a suitable number of spaces at the
96 * beginning corresponding to the given indent.
97 */
98 protected void writeLine(int indentIndex, String string) throws IOException
99 {
100
101
102
103 int indent = (indentIndex-1)*INDENT_SIZE;
104 if (indent<0)
105 {
106 indent = 0;
107 }
108
109
110 while (indentSpaces.length() < indent)
111 {
112 indentSpaces = indentSpaces + indentSpaces;
113 }
114
115 writeString(indentSpaces.substring(0, indent) + string + "\n");
116 }
117
118 /***
119 * Close tag - and output stream
120 */
121 public void close() throws IOException
122 {
123 super.close();
124 out.close();
125 }
126
127
128 /*** Test harness method - writes out a simple table
129 */
130 public static void main(String args[])
131 {
132 System.out.println("Hello World!");
133
134 try
135 {
136 XmlPrinter xOut = new XmlPrinter(new OutputStreamWriter(System.out), true);
137
138 XmlTagPrinter ftag = xOut.newTag("FRUIT");
139
140 ftag.writeTag("DESCRIPTION","Sort of fruity things");
141
142 XmlTagPrinter atag = ftag.newTag("APPLE");
143 atag.writeTag("SKIN","Rosy");
144 atag.writeTag("FLESH","White & Powdery");
145 atag.writeTag("STALK","Yes unless it's fallen off");
146 atag.close();
147
148 XmlTagPrinter otag = ftag.newTag("ORANGE");
149 otag.writeTag("SKIN","Orange");
150 otag.writeTag("FLESH","Really Orange. Or Red.");
151 otag.writeTag("STALK","Would be orange but I've eaten it");
152
153
154 xOut.close();
155
156 } catch (IOException ioe)
157 {
158 System.out.println("IOE: "+ioe);
159 }
160
161 System.out.println("Goodbye Cruel World!");
162
163 }
164 }
165
166