1 9 package javolution.xml.sax; 10 11 import java.io.IOException; 12 import java.io.Writer; 13 14 import j2me.lang.CharSequence; 15 import javolution.lang.Reusable; 16 import javolution.lang.Text; 17 import javolution.util.FastList; 18 19 import org.xml.sax.Locator; 20 import org.xml.sax.SAXException; 21 22 28 public class WriterHandler implements ContentHandler, Reusable { 29 30 33 private static final int BUFFER_LENGTH = 2048; 34 35 38 private Writer _writer; 39 40 43 private CharSequence _prolog = Text.EMPTY; 44 45 48 private CharSequence _indent = Text.EMPTY; 49 50 53 private FastList _prefixMappings = new FastList(); 54 55 58 private int _nesting = -1; 59 60 64 private boolean _isTagOpen; 65 66 69 private final char[] _buffer = new char[BUFFER_LENGTH]; 70 71 74 private int _index; 75 76 79 public WriterHandler() { 80 } 81 82 88 public WriterHandler setWriter(Writer writer) { 89 _writer = writer; 90 return this; 91 } 92 93 98 public void setIndent(CharSequence indent) { 99 _indent = indent; 100 } 101 102 109 public void setProlog(CharSequence prolog) { 110 _prolog = prolog; 111 } 112 113 public void reset() { 115 _writer = null; 116 _indent = Text.EMPTY; 117 _prolog = Text.EMPTY; 118 _prefixMappings.clear(); 119 _nesting = -1; 120 _isTagOpen = false; 121 _index = 0; 122 } 123 124 public void setDocumentLocator(Locator locator) { 126 } 128 129 public void startDocument() throws SAXException { 131 if (_writer == null) 132 throw new SAXException("Writer not set"); 133 try { 134 writeNoEscape(_prolog); 135 } catch (IOException e) { 136 throw new SAXException(e); 137 } 138 } 139 140 public void endDocument() throws SAXException { 142 try { 143 flushBuffer(); 144 _writer.close(); 145 } catch (IOException e) { 146 throw new SAXException(e); 147 } 148 } 149 150 public void startPrefixMapping(CharSequence prefix, CharSequence uri) 152 throws SAXException { 153 _prefixMappings.addLast(prefix); 154 _prefixMappings.addLast(uri); 155 } 156 157 public void endPrefixMapping(CharSequence prefix) throws SAXException { 159 } 161 162 public void startElement(CharSequence uri, CharSequence localName, 164 CharSequence qName, Attributes atts) throws SAXException { 165 try { 166 if (_isTagOpen) { writeNoEscape(">\n"); 168 _isTagOpen = false; 169 } 170 171 _nesting++; 173 indent(); 174 175 writeNoEscape('<'); 177 writeNoEscape(qName); 178 179 if (_prefixMappings.size() > 0) { 181 writeNamespaces(); 182 } 183 184 final int attsLength = atts.getLength(); 186 for (int i = 0; i < attsLength; i++) { 187 CharSequence attName = atts.getQName(i); 188 CharSequence attValue = atts.getValue(i); 189 writeNoEscape(' '); 190 writeNoEscape(attName); 191 writeNoEscape('='); 192 writeNoEscape('"'); 193 write(attValue); 194 writeNoEscape('"'); 195 } 196 _isTagOpen = true; 197 } catch (IOException e) { 198 throw new SAXException(e); 199 } 200 } 201 202 private void indent() throws IOException { 203 final int length = _indent.length(); 204 if (length > 0) { 205 for (int i = 0; i < _nesting; i++) { 206 writeNoEscape(_indent); 207 } 208 } 209 } 210 211 private void writeNamespaces() throws IOException { 212 for (FastList.Node n = _prefixMappings.headNode(), end = _prefixMappings 214 .tailNode(); (n = n.getNextNode()) != end;) { 215 CharSequence prefix = (CharSequence) n.getValue(); 216 CharSequence prefixUri = (CharSequence) (n = n.getNextNode()) 217 .getValue(); 218 if (prefix.length() == 0) { writeNoEscape(" xmlns=\""); 220 write(prefixUri); 221 writeNoEscape('"'); 222 } else { 223 writeNoEscape(" xmlns:"); 224 writeNoEscape(prefix); 225 writeNoEscape('='); 226 writeNoEscape('"'); 227 write(prefixUri); 228 writeNoEscape('"'); 229 } 230 } 231 _prefixMappings.clear(); 232 } 233 234 public void endElement(CharSequence uri, CharSequence localName, 236 CharSequence qName) throws SAXException { 237 try { 238 if (_isTagOpen) { writeNoEscape("/>\n"); 240 _isTagOpen = false; 241 } else { 242 indent(); 243 writeNoEscape('<'); 244 writeNoEscape('/'); 245 writeNoEscape(qName); 246 writeNoEscape('>'); 247 writeNoEscape('\n'); 248 } 249 _nesting--; 250 } catch (IOException e) { 251 throw new SAXException(e); 252 } 253 } 254 255 public void characters(char[] ch, int start, int length) 257 throws SAXException { 258 try { 259 if (_isTagOpen) { writeNoEscape('>'); 261 _isTagOpen = false; 262 } 263 writeNoEscape("<![CDATA["); 264 flushBuffer(); 265 _writer.write(ch, start, length); 266 writeNoEscape("]]>\n"); 267 } catch (IOException e) { 268 throw new SAXException(e); 269 } 270 } 271 272 public void ignorableWhitespace(char[] ch, int start, int length) 274 throws SAXException { 275 } 277 278 public void processingInstruction(CharSequence target, CharSequence data) 280 throws SAXException { 281 } 283 284 public void skippedEntity(CharSequence name) throws SAXException { 286 } 288 289 private void write(CharSequence csq) throws IOException { 291 final int length = csq.length(); 292 for (int i = 0; i < length;) { 293 char c = csq.charAt(i++); 294 if ((c >= '@') || (c == ' ')) { _buffer[_index] = c; 296 if (++_index == BUFFER_LENGTH) { 297 flushBuffer(); 298 } 299 } else { switch (c) { 301 case '<': 302 writeNoEscape("<"); 303 break; 304 case '>': 305 writeNoEscape(">"); 306 break; 307 case '\'': 308 writeNoEscape("'"); 309 break; 310 case '\"': 311 writeNoEscape("""); 312 break; 313 case '&': 314 writeNoEscape("&"); 315 break; 316 default: 317 if (c >= ' ') { 318 writeNoEscape(c); 319 } else { 320 writeNoEscape("&#"); 321 writeNoEscape((char) ('0' + c / 10)); 322 writeNoEscape((char) ('0' + c % 10)); 323 writeNoEscape(';'); 324 } 325 } 326 } 327 } 328 } 329 330 private void writeNoEscape(CharSequence csq) throws IOException { 331 for (int i = 0, n = csq.length(); i < n;) { 332 _buffer[_index] = csq.charAt(i++); 333 if (++_index == BUFFER_LENGTH) { 334 flushBuffer(); 335 } 336 } 337 } 338 339 private void writeNoEscape(String csq) throws IOException { 340 for (int i = 0, n = csq.length(); i < n;) { 341 _buffer[_index] = csq.charAt(i++); 342 if (++_index == BUFFER_LENGTH) { 343 flushBuffer(); 344 } 345 } 346 } 347 348 private final void writeNoEscape(char c) throws IOException { 349 _buffer[_index] = c; 350 if (++_index == BUFFER_LENGTH) { 351 flushBuffer(); 352 } 353 } 354 355 private void flushBuffer() throws IOException { 356 _writer.write(_buffer, 0, _index); 357 _index = 0; 358 } 359 360 } | Popular Tags |