1 package org.dbunit.util.xml; 2 3 56 57 import java.io.IOException ; 58 import java.io.OutputStreamWriter ; 59 import java.io.Writer ; 60 import java.util.Stack ; 61 62 71 public class XmlWriter 72 { 73 74 private Writer out; private String encoding; 76 private Stack stack = new Stack (); private StringBuffer attrs; private boolean empty; private boolean closed = true; 81 private boolean pretty = true; private boolean wroteText = false; private String indent = " "; private String newline = "\n"; 86 89 public XmlWriter(Writer writer) 90 { 91 this(writer, null); 92 } 93 94 97 public XmlWriter(Writer writer, String encoding) 98 { 99 setWriter(writer, encoding); 100 } 101 102 109 public void enablePrettyPrint(boolean enable) 110 { 111 this.pretty = enable; 112 } 113 114 122 public void setIndent(String indent) 123 { 124 this.indent = indent; 125 } 126 127 137 public void setNewline(String newline) 138 { 139 this.newline = newline; 140 } 141 142 148 public XmlWriter writeElementWithText(String name, String text) throws IOException 149 { 150 writeElement(name); 151 writeText(text); 152 return endElement(); 153 } 154 155 160 public XmlWriter writeEmptyElement(String name) throws IOException 161 { 162 writeElement(name); 163 return endElement(); 164 } 165 166 172 public XmlWriter writeElement(String name) throws IOException 173 { 174 return openElement(name); 175 } 176 177 182 private XmlWriter openElement(String name) throws IOException 183 { 184 boolean wasClosed = this.closed; 185 closeOpeningTag(); 186 this.closed = false; 187 if (this.pretty) 188 { 189 if (!wasClosed || this.wroteText) 195 { 196 this.out.write(newline); 197 } 198 for (int i = 0; i < this.stack.size(); i++) 199 { 200 this.out.write(indent); } 202 } 203 this.out.write("<"); 204 this.out.write(name); 205 stack.add(name); 206 this.empty = true; 207 this.wroteText = false; 208 return this; 209 } 210 211 private void closeOpeningTag() throws IOException 213 { 214 if (!this.closed) 215 { 216 writeAttributes(); 217 this.closed = true; 218 this.out.write(">"); 219 } 220 } 221 222 private void writeAttributes() throws IOException 224 { 225 if (this.attrs != null) 226 { 227 this.out.write(this.attrs.toString()); 228 this.attrs.setLength(0); 229 this.empty = false; 230 } 231 } 232 233 242 public XmlWriter writeAttribute(String attr, String value) throws IOException 243 { 244 245 if (false) throw new IOException (); 247 248 if (this.attrs == null) 249 { 250 this.attrs = new StringBuffer (); 251 } 252 this.attrs.append(" "); 253 this.attrs.append(attr); 254 this.attrs.append("=\""); 255 this.attrs.append(escapeXml(value)); 256 this.attrs.append("\""); 257 return this; 258 } 259 260 265 public XmlWriter endElement() throws IOException 266 { 267 if (this.stack.empty()) 268 { 269 throw new IOException ("Called endElement too many times. "); 270 } 271 String name = (String )this.stack.pop(); 272 if (name != null) 273 { 274 if (this.empty) 275 { 276 writeAttributes(); 277 this.out.write("/>"); 278 } 279 else 280 { 281 if (this.pretty && !this.wroteText) 282 { 283 for (int i = 0; i < this.stack.size(); i++) 284 { 285 this.out.write(indent); } 287 } 288 this.out.write("</"); 289 this.out.write(name); 290 this.out.write(">"); 291 } 292 if (this.pretty) 293 this.out.write(newline); this.empty = false; 295 this.closed = true; 296 this.wroteText = false; 297 } 298 return this; 299 } 300 301 306 public void close() throws IOException 307 { 308 this.out.flush(); 309 310 if (!this.stack.empty()) 311 { 312 throw new IOException ("Tags are not all closed. " + 313 "Possibly, " + this.stack.pop() + " is unclosed. "); 314 } 315 } 316 317 320 public XmlWriter writeText(String text) throws IOException 321 { 322 closeOpeningTag(); 323 this.empty = false; 324 this.wroteText = true; 325 this.out.write(escapeXml(text)); 326 return this; 327 } 328 329 335 public XmlWriter writeCData(String cdata) throws IOException 336 { 337 closeOpeningTag(); 338 this.empty = false; 339 this.wroteText = true; 340 this.out.write("<![CDATA["); 341 this.out.write(cdata); 342 this.out.write("]]>"); 343 return this; 344 } 345 346 352 public XmlWriter writeComment(String comment) throws IOException 353 { 354 writeChunk("<!-- " + comment + " -->"); 355 return this; 356 } 357 358 private void writeChunk(String data) throws IOException 359 { 360 closeOpeningTag(); 361 this.empty = false; 362 if (this.pretty && !this.wroteText) 363 { 364 for (int i = 0; i < this.stack.size(); i++) 365 { 366 this.out.write(indent); 367 } 368 } 369 370 this.out.write(data); 371 372 if (this.pretty) 373 { 374 this.out.write(newline); 375 } 376 } 377 378 static public void main(String [] args) throws IOException 381 { 382 test1(); 383 test2(); 384 } 385 386 static public void test1() throws IOException 387 { 388 Writer writer = new java.io.StringWriter (); 389 XmlWriter xmlwriter = new XmlWriter(writer); 390 xmlwriter.writeElement("person").writeAttribute("name", "fred").writeAttribute("age", "12").writeElement("phone").writeText("4254343").endElement().writeElement("friends").writeElement("bob").endElement().writeElement("jim").endElement().endElement().endElement(); 391 xmlwriter.close(); 392 System.err.println(writer.toString()); 393 } 394 395 static public void test2() throws IOException 396 { 397 Writer writer = new java.io.StringWriter (); 398 XmlWriter xmlwriter = new XmlWriter(writer); 399 xmlwriter.writeComment("Example of XmlWriter running"); 400 xmlwriter.writeElement("person"); 401 xmlwriter.writeAttribute("name", "fred"); 402 xmlwriter.writeAttribute("age", "12"); 403 xmlwriter.writeElement("phone"); 404 xmlwriter.writeText("4254343"); 405 xmlwriter.endElement(); 406 xmlwriter.writeComment("Examples of empty tags"); 407 xmlwriter.writeElement("friends"); 409 xmlwriter.writeEmptyElement("bob"); 410 xmlwriter.writeEmptyElement("jim"); 411 xmlwriter.endElement(); 412 xmlwriter.writeElementWithText("foo", "This is an example."); 413 xmlwriter.endElement(); 414 xmlwriter.close(); 415 System.err.println(writer.toString()); 416 } 417 418 421 private String escapeXml(String str) 422 { 423 str = replace(str, "&", "&"); 424 str = replace(str, "<", "<"); 425 str = replace(str, ">", ">"); 426 str = replace(str, "\"", """); 427 str = replace(str, "'", "'"); 428 return str; 429 } 430 431 private String replace(String value, String original, String replacement) 432 { 433 StringBuffer buffer = null; 434 435 int startIndex = 0; 436 int lastEndIndex = 0; 437 for (; ;) 438 { 439 startIndex = value.indexOf(original, lastEndIndex); 440 if (startIndex == -1) 441 { 442 if (buffer != null) 443 { 444 buffer.append(value.substring(lastEndIndex)); 445 } 446 break; 447 } 448 449 if (buffer == null) 450 { 451 buffer = new StringBuffer ((int)(original.length() * 1.5)); 452 } 453 buffer.append(value.substring(lastEndIndex, startIndex)); 454 buffer.append(replacement); 455 lastEndIndex = startIndex + original.length(); 456 } 457 458 return buffer == null ? value : buffer.toString(); 459 } 460 461 private void setEncoding(String encoding) 462 { 463 if (encoding == null && out instanceof OutputStreamWriter ) 464 encoding = ((OutputStreamWriter )out).getEncoding(); 465 466 if (encoding != null) 467 { 468 encoding = encoding.toUpperCase(); 469 470 476 if ("UTF8".equals(encoding)) 478 { 479 encoding = "UTF-8"; 480 } 481 else if ("US-ASCII".equals(encoding) 482 || "ASCII".equals(encoding)) 483 { 484 encoding = "US-ASCII"; 486 } 487 else if ("ISO-8859-1".equals(encoding) 488 || "8859_1".equals(encoding) 489 || "ISO8859_1".equals(encoding)) 490 { 491 encoding = "ISO-8859-1"; 493 } 494 else if ("UNICODE".equals(encoding) 495 || "UNICODE-BIG".equals(encoding) 496 || "UNICODE-LITTLE".equals(encoding)) 497 { 498 encoding = "UTF-16"; 499 500 } 503 504 } 507 508 this.encoding = encoding; 509 } 510 511 512 522 final public void setWriter(Writer writer, String encoding) 523 { 524 if (this.out != null) 525 throw new IllegalStateException ( 526 "can't change stream in mid course"); 527 this.out = writer; 528 if (this.out != null) 529 setEncoding(encoding); 530 } 533 534 public XmlWriter writeDeclaration() throws IOException 535 { 536 if (this.encoding != null) 537 { 538 this.out.write("<?xml version='1.0'"); 539 this.out.write(" encoding='" + this.encoding + "'"); 540 this.out.write("?>"); 541 this.out.write(this.newline); 542 } 543 544 return this; 545 } 546 547 public XmlWriter writeDoctype(String systemId, String publicId) throws IOException 548 { 549 if (systemId != null || publicId != null) 550 { 551 this.out.write("<!DOCTYPE dataset"); 552 553 if (systemId != null) 554 { 555 this.out.write(" SYSTEM \""); 556 this.out.write(systemId); 557 this.out.write("\""); 558 } 559 560 if (publicId != null) 561 { 562 this.out.write(" PUBLIC \""); 563 this.out.write(publicId); 564 this.out.write("\""); 565 } 566 567 this.out.write(">"); 568 this.out.write(this.newline); 569 } 570 571 return this; 572 } 573 574 } 575 | Popular Tags |