1 16 package org.apache.cocoon.components.serializers; 17 18 import java.io.CharArrayWriter ; 19 20 import org.apache.cocoon.components.serializers.encoding.XMLEncoder; 21 import org.apache.cocoon.components.serializers.util.DocType; 22 import org.apache.cocoon.components.serializers.util.Namespaces; 23 import org.apache.commons.lang.SystemUtils; 24 import org.xml.sax.SAXException ; 25 26 31 public class XMLSerializer extends EncodingSerializer { 32 33 private static final XMLEncoder XML_ENCODER = new XMLEncoder(); 34 35 private static final char S_EOL[] = SystemUtils.LINE_SEPARATOR.toCharArray(); 36 37 private static final char S_DOCUMENT_1[] = "<?xml version=\"1.0".toCharArray(); 38 private static final char S_DOCUMENT_2[] = "\" encoding=\"".toCharArray(); 39 private static final char S_DOCUMENT_3[] = "\"?>".toCharArray(); 40 41 private static final char S_ELEMENT_1[] = "=\"".toCharArray(); 42 private static final char S_ELEMENT_2[] = "</".toCharArray(); 43 private static final char S_ELEMENT_3[] = " />".toCharArray(); 44 private static final char S_ELEMENT_4[] = " xmlns".toCharArray(); 45 46 private static final char S_CDATA_1[] = "<[CDATA[".toCharArray(); 47 private static final char S_CDATA_2[] = "]]>".toCharArray(); 48 49 private static final char S_COMMENT_1[] = "<!--".toCharArray(); 50 private static final char S_COMMENT_2[] = "-->".toCharArray(); 51 52 private static final char S_PROCINSTR_1[] = "<?".toCharArray(); 53 private static final char S_PROCINSTR_2[] = "?>".toCharArray(); 54 55 private static final char C_LT = '<'; 56 private static final char C_GT = '>'; 57 private static final char C_SPACE = ' '; 58 private static final char C_QUOTE = '"'; 59 private static final char C_NSSEP = ':'; 60 61 private static final boolean DEBUG = false; 62 63 64 65 66 private boolean hanging_element = false; 67 68 69 private boolean processing_prolog = true; 70 71 72 private boolean processing_dtd = false; 73 74 75 private PrologWriter prolog = new PrologWriter(); 76 77 78 79 80 protected DocType doctype = null; 81 82 83 84 87 public XMLSerializer() { 88 super(XML_ENCODER); 89 } 90 91 94 protected XMLSerializer(XMLEncoder encoder) { 95 super(encoder); 96 } 97 98 101 public void recycle() { 102 super.recycle(); 103 this.doctype = null; 104 this.hanging_element = false; 105 this.processing_prolog = true; 106 this.processing_dtd = false; 107 if (this.prolog != null) this.prolog.reset(); 108 } 109 110 113 public String getMimeType() { 114 if (this.charset == null) return("text/xml"); 115 return("text/xml; charset=" + this.charset.getName()); 116 } 117 118 119 120 123 public void startDocument() 124 throws SAXException { 125 super.startDocument(); 126 this.head(); 127 } 128 129 132 public void endDocument() 133 throws SAXException { 134 this.writeln(); 135 super.endDocument(); 136 } 137 138 145 protected void head() 146 throws SAXException { 147 this.write(S_DOCUMENT_1); if (this.charset != null) { 149 this.write(S_DOCUMENT_2); this.write(this.charset.getName()); 151 } 152 this.write(S_DOCUMENT_3); this.writeln(); 154 } 155 156 159 public void startDTD(String name, String public_id, String system_id) 160 throws SAXException { 161 this.processing_dtd = true; 162 this.doctype = new DocType(name, public_id, system_id); 163 } 164 165 168 public void endDTD() 169 throws SAXException { 170 this.processing_dtd = false; 171 } 172 173 180 public void body(String uri, String local, String qual) 181 throws SAXException { 182 this.processing_prolog = false; 183 this.writeln(); 184 185 186 if (this.doctype != null) { 187 188 String root_name = this.doctype.getName(); 189 190 if (!root_name.equals(qual)) { 191 throw new SAXException ("Root element name \"" + root_name 192 + "\" declared by document type declaration differs " 193 + "from actual root element name \"" + qual + "\""); 194 } 195 196 this.write(this.doctype.toString()); 197 } 198 199 200 this.prolog.writeTo(this); 201 this.writeln(); 202 } 203 204 215 public void startElementImpl(String uri, String local, String qual, 216 String namespaces[][], String attributes[][]) 217 throws SAXException { 218 this.closeElement(false); 219 this.write(C_LT); if (DEBUG) { 221 this.write('['); 222 this.write(uri); 223 this.write(']'); 224 } 225 this.write(qual); 226 227 for (int x = 0; x < namespaces.length; x++) { 228 this.write(S_ELEMENT_4); if (namespaces[x][Namespaces.NAMESPACE_PREFIX].length() > 0) { 230 this.write(C_NSSEP); this.write(namespaces[x][Namespaces.NAMESPACE_PREFIX]); 232 } 233 this.write(S_ELEMENT_1); this.encode(namespaces[x][Namespaces.NAMESPACE_URI]); 235 this.write(C_QUOTE); } 237 238 for (int x = 0; x < attributes.length; x++) { 239 this.write(C_SPACE); if (DEBUG) { 241 this.write('['); 242 this.write(attributes[x][ATTRIBUTE_NSURI]); 243 this.write(']'); 244 } 245 this.write(attributes[x][ATTRIBUTE_QNAME]); 246 this.write(S_ELEMENT_1); this.encode(attributes[x][ATTRIBUTE_VALUE]); 248 this.write(C_QUOTE); } 250 251 this.hanging_element = true; 252 } 253 254 261 public void endElementImpl(String uri, String local, String qual) 262 throws SAXException { 263 if (closeElement(true)) return; 264 this.write(S_ELEMENT_2); if (DEBUG) { 266 this.write('['); 267 this.write(uri); 268 this.write(']'); 269 } 270 this.write(qual); 271 this.write(C_GT); } 273 274 282 protected boolean closeElement(boolean end_element) 283 throws SAXException { 284 if (!hanging_element) return(false); 285 if (end_element) this.write(S_ELEMENT_3); else this.write(C_GT); this.hanging_element = false; 288 return(true); 289 } 290 291 294 public void startCDATA() 295 throws SAXException { 296 if (this.processing_prolog) return; 297 this.closeElement(false); 298 this.write(S_CDATA_1); } 300 301 304 public void endCDATA() 305 throws SAXException { 306 if (this.processing_prolog) return; 307 this.closeElement(false); 308 this.write(S_CDATA_2); } 310 311 314 public void charactersImpl(char data[], int start, int length) 315 throws SAXException { 316 if (this.processing_prolog) return; 317 this.closeElement(false); 318 this.encode(data, start, length); 319 } 320 321 324 public void ignorableWhitespace(char data[], int start, int length) 325 throws SAXException { 326 this.charactersImpl(data, start, length); 327 } 328 329 332 public void comment(char data[], int start, int length) 333 throws SAXException { 334 if (this.processing_dtd) return; 335 336 if (this.processing_prolog) { 337 this.prolog.write(S_COMMENT_1); this.prolog.write(data, start, length); 339 this.prolog.write(S_COMMENT_2); this.prolog.write(S_EOL); 341 return; 342 } 343 344 this.closeElement(false); 345 this.write(S_COMMENT_1); this.write(data, start, length); 347 this.write(S_COMMENT_2); } 349 350 353 public void processingInstruction(String target, String data) 354 throws SAXException { 355 if (this.processing_dtd) return; 356 357 if (this.processing_prolog) { 358 this.prolog.write(S_PROCINSTR_1); this.prolog.write(target); 360 if (data != null) { 361 this.prolog.write(C_SPACE); this.prolog.write(data); 363 } 364 this.prolog.write(S_PROCINSTR_2); this.prolog.write(S_EOL); 366 return; 367 } 368 369 this.closeElement(false); 370 371 this.write(S_PROCINSTR_1); this.write(target); 373 if (data != null) { 374 this.write(C_SPACE); this.write(data); 376 } 377 this.write(S_PROCINSTR_2); } 379 380 383 public void startEntity(String name) 384 throws SAXException { 385 } 386 387 390 public void endEntity(String name) 391 throws SAXException { 392 } 393 394 397 public void skippedEntity(String name) 398 throws SAXException { 399 } 400 401 402 403 407 private static final class PrologWriter extends CharArrayWriter { 408 409 410 private PrologWriter() { 411 super(); 412 } 413 414 421 public void write(char c[]) { 422 this.write(c, 0, c.length); 423 } 424 425 432 public void write(String str) { 433 this.write(str, 0, str.length()); 434 } 435 436 440 public void writeTo(XMLSerializer serializer) 441 throws SAXException { 442 serializer.write(this.buf, 0, this.count); 443 } 444 } 445 } 446 | Popular Tags |