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 */ 017package org.apache.xbean.spring.generator; 018 019import java.io.PrintWriter; 020import java.io.Writer; 021import java.util.LinkedList; 022 023/** 024 * @author Dain Sundstrom 025 * @version $Id$ 026 * @since 1.0 027 */ 028public 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}