001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.xbean.spring.generator;
018
019 import java.io.PrintWriter;
020 import java.io.Writer;
021 import java.util.LinkedList;
022
023 /**
024 * @author Dain Sundstrom
025 * @version $Id$
026 * @since 1.0
027 */
028 public class XmlWriter {
029 private PrintWriter writer;
030
031 private LinkedList elementStack = new LinkedList();
032
033 private boolean tagInProgress;
034
035 private int depth;
036
037 private String lineIndenter;
038
039 private String encoding;
040
041 private String docType;
042
043 private boolean readyForNewLine;
044
045 private boolean tagIsEmpty;
046
047 public XmlWriter(PrintWriter writer, String lineIndenter) {
048 this(writer, lineIndenter, null, null);
049 }
050
051 public XmlWriter(Writer writer, String lineIndenter) {
052 this(new PrintWriter(writer), lineIndenter);
053 }
054
055 public XmlWriter(PrintWriter writer) {
056 this(writer, null, null);
057 }
058
059 public XmlWriter(Writer writer) {
060 this(new PrintWriter(writer));
061 }
062
063 public XmlWriter(PrintWriter writer, String lineIndenter, String encoding, String doctype) {
064 this.writer = writer;
065
066 this.lineIndenter = lineIndenter;
067
068 this.encoding = encoding;
069
070 this.docType = doctype;
071
072 if (docType != null || encoding != null) {
073 writeDocumentHeaders();
074 }
075 }
076
077 public XmlWriter(Writer writer, String lineIndenter, String encoding, String doctype) {
078 this(new PrintWriter(writer), lineIndenter, encoding, doctype);
079 }
080
081 public XmlWriter(PrintWriter writer, String encoding, String doctype) {
082 this(writer, " ", encoding, doctype);
083 }
084
085 public XmlWriter(Writer writer, String encoding, String doctype) {
086 this(new PrintWriter(writer), encoding, doctype);
087 }
088
089 public void startElement(String name) {
090 tagIsEmpty = false;
091
092 finishTag();
093
094 write("<");
095
096 write(name);
097
098 elementStack.addLast(name);
099
100 tagInProgress = true;
101
102 depth++;
103
104 readyForNewLine = true;
105
106 tagIsEmpty = true;
107 }
108
109 public void writeText(String text) {
110 writeText(text, true);
111 }
112
113 public void writeMarkup(String text) {
114 writeText(text, false);
115 }
116
117 private void writeText(String text, boolean escapeHtml) {
118 readyForNewLine = false;
119
120 tagIsEmpty = false;
121
122 finishTag();
123
124 if (escapeHtml) {
125 text = text.replaceAll("&", "&");
126
127 text = text.replaceAll("<", "<");
128
129 text = text.replaceAll(">", ">");
130 }
131
132 write(text);
133 }
134
135 public void addAttribute(String key, String value) {
136 write(" ");
137
138 write(key);
139
140 write("=\"");
141
142 write(value);
143
144 write("\"");
145 }
146
147 public void endElement() {
148 depth--;
149
150 if (tagIsEmpty) {
151 write("/");
152
153 readyForNewLine = false;
154
155 finishTag();
156
157 elementStack.removeLast();
158 } else {
159 finishTag();
160
161 write("</" + elementStack.removeLast() + ">");
162 }
163
164 readyForNewLine = true;
165 }
166
167 private void write(String str) {
168 writer.write(str);
169 }
170
171 private void finishTag() {
172 if (tagInProgress) {
173 write(">");
174 }
175
176 tagInProgress = false;
177
178 if (readyForNewLine) {
179 endOfLine();
180 }
181 readyForNewLine = false;
182
183 tagIsEmpty = false;
184 }
185
186 protected void endOfLine() {
187 write("\n");
188
189 for (int i = 0; i < depth; i++) {
190 write(lineIndenter);
191 }
192 }
193
194 private void writeDocumentHeaders() {
195 write("<?xml version=\"1.0\"");
196
197 if (encoding != null) {
198 write(" encoding=\"" + encoding + "\"");
199 }
200
201 write("?>");
202
203 endOfLine();
204
205 if (docType != null) {
206 write("<!DOCTYPE ");
207
208 write(docType);
209
210 write(">");
211
212 endOfLine();
213 }
214 }
215 }