| 1 4 package org.znerd.xmlenc; 5 6 import java.io.IOException ; 7 import java.io.UnsupportedEncodingException ; 8 import java.io.Writer ; 9 10 80 public class XMLOutputter 81 extends Object  82 implements StatefulXMLEventListener { 83 84 88 92 96 public static final String DEFAULT_INDENTATION = ""; 97 98 99 103 107 public XMLOutputter() { 108 _elementStack = new String [16]; 109 _quotationMark = '"'; 110 } 111 112 137 public XMLOutputter(Writer out, String encoding) 138 throws IllegalStateException , 139 IllegalArgumentException , 140 UnsupportedEncodingException { 141 142 this(); 143 144 reset(out, encoding); 146 } 147 148 149 171 public XMLOutputter(Writer out, XMLEncoder encoder) 172 throws IllegalStateException , 173 IllegalArgumentException , 174 UnsupportedEncodingException { 175 176 this(); 177 178 reset(out, encoder); 180 } 181 182 186 194 private Writer _out; 195 196 199 private XMLEncoder _encoder; 200 201 204 private XMLEventListenerState _state = UNINITIALIZED; 205 206 214 private String [] _elementStack; 215 216 222 private int _elementStackSize; 223 224 231 private char _quotationMark; 232 233 236 private boolean _escapeAmpersands = true; 237 238 242 private LineBreak _lineBreak = LineBreak.NONE; 243 244 248 private char[] _lineBreakChars = _lineBreak._lineBreakChars; 249 250 254 private String _indentation; 255 256 257 261 268 private final void checkInvariants() 269 throws Error { 270 } 272 273 279 private final void writeIndentation() 280 throws IOException { 281 282 if (_indentation.length() != 0) { 284 int count = _elementStackSize - 1; 285 for (int i = 0; i < count; i++) { 286 _out.write(_indentation); 287 } 288 } 289 } 290 291 298 public final Writer getWriter() { 299 return _out; 300 } 301 302 309 public final String getEncoding() { 310 if (_encoder == null) { 311 return null; 312 } else { 313 return _encoder.getEncoding(); 314 } 315 } 316 317 324 public void reset() { 325 _out = null; 326 _encoder = null; 327 _elementStackSize = 0; 328 _state = UNINITIALIZED; 329 _lineBreak = LineBreak.NONE; 330 _lineBreakChars = _lineBreak._lineBreakChars; 331 _indentation = DEFAULT_INDENTATION; 332 333 checkInvariants(); 335 } 336 337 348 private final void reset(Writer out) 349 throws IllegalArgumentException { 350 351 if (out == null) { 353 throw new IllegalArgumentException ("out == null"); 354 } 355 356 _out = out; 358 _state = BEFORE_XML_DECLARATION; 359 _elementStackSize = 0; 360 _lineBreak = LineBreak.NONE; 361 _lineBreakChars = _lineBreak._lineBreakChars; 362 _indentation = DEFAULT_INDENTATION; 363 364 checkInvariants(); 366 } 367 368 385 public final void reset(Writer out, String encoding) 386 throws IllegalArgumentException , 387 UnsupportedEncodingException { 388 389 if (encoding == null) { 391 throw new IllegalArgumentException ("encoding == null"); 392 } 393 394 reset(out); 395 396 _encoder = XMLEncoder.getEncoder(encoding); 398 399 checkInvariants(); 401 } 402 403 420 public final void reset(Writer out, XMLEncoder encoder) 421 throws IllegalArgumentException , 422 UnsupportedEncodingException { 423 424 if (encoder == null) { 426 throw new IllegalArgumentException ("encoder == null"); 427 } 428 429 reset(out); 430 431 _encoder = encoder; 433 434 checkInvariants(); 436 } 437 438 466 public final void setState(XMLEventListenerState newState, String [] newElementStack) 467 throws IllegalArgumentException { 468 469 if (newState == null) { 471 throw new IllegalArgumentException ("newState == null"); 472 } else if (newState == START_TAG_OPEN && newElementStack == null) { 473 throw new IllegalArgumentException ("newState == START_TAG_OPEN && newElementStack == null"); 474 } else if (newState == WITHIN_ELEMENT && newElementStack == null) { 475 throw new IllegalArgumentException ("newState == WITHIN_ELEMENT && newElementStack == null"); 476 } else if (newState != START_TAG_OPEN && newState != WITHIN_ELEMENT && newElementStack != null) { 477 throw new IllegalArgumentException ("newState != START_TAG_OPEN && newState != WITHIN_ELEMENT && newElementStack != null"); 478 } 479 480 if (newElementStack != null) { 481 for (int i = 0; i < newElementStack.length; i++) { 482 if (newElementStack[i] == null) { 483 throw new IllegalArgumentException ("newElementStack[" + i + "] == null"); 484 } 485 } 486 487 if (newElementStack.length > _elementStack.length) { 488 try { 489 _elementStack = new String [newElementStack.length + 16]; 490 } catch (OutOfMemoryError error) { 491 _elementStack = new String [newElementStack.length]; 492 } 493 } 494 System.arraycopy(newElementStack, 0, _elementStack, 0, newElementStack.length); 495 } 496 497 if (newState == UNINITIALIZED) { 498 reset(); 499 } else { 500 _state = newState; 501 _elementStackSize = newElementStack == null ? 0 : newElementStack.length; 502 } 503 504 checkInvariants(); 506 } 507 508 514 public final XMLEventListenerState getState() { 515 return _state; 516 } 517 518 530 public final boolean isEscaping() { 531 return _escapeAmpersands; 532 } 533 534 549 public final void setEscaping(boolean escapeAmpersands) { 550 _escapeAmpersands = escapeAmpersands; 551 552 checkInvariants(); 554 } 555 556 568 public final String [] getElementStack() { 569 if (_elementStackSize == 0) { 570 return null; 571 } else { 572 String [] newStack = new String [_elementStackSize]; 573 System.arraycopy(_elementStack, 0, newStack, 0, _elementStackSize); 574 return newStack; 575 } 576 } 577 578 586 public final int getElementStackSize() { 587 return _elementStackSize; 588 } 589 590 599 public final int getElementStackCapacity() { 600 return _elementStack.length; 601 } 602 603 617 public final void setElementStackCapacity(int newCapacity) 618 throws IllegalArgumentException , OutOfMemoryError { 619 620 if (newCapacity < _elementStack.length) { 622 throw new IllegalArgumentException ("newCapacity < getElementStackSize()"); 623 } 624 625 int currentCapacity = _elementStack.length; 626 627 if (currentCapacity == newCapacity) { 629 return; 630 } 631 632 String [] newStack = new String [newCapacity]; 633 System.arraycopy(_elementStack, 0, newStack, 0, _elementStackSize); 634 _elementStack = newStack; 635 636 checkInvariants(); 638 } 639 640 654 public final void setQuotationMark(char c) 655 throws IllegalArgumentException { 656 657 if (c == '\'' || c == '"') { 659 _quotationMark = c; 660 661 } else { 663 throw new IllegalArgumentException ("c != '\\'' && c != '\"'"); 664 } 665 666 checkInvariants(); 668 } 669 670 680 public final char getQuotationMark() { 681 return _quotationMark; 682 } 683 684 691 public final void setLineBreak(LineBreak lineBreak) { 692 _lineBreak = lineBreak != null 693 ? lineBreak 694 : LineBreak.NONE; 695 _lineBreakChars = _lineBreak._lineBreakChars; 696 697 checkInvariants(); 699 } 700 701 707 public final LineBreak getLineBreak() { 708 return _lineBreak; 709 } 710 711 718 public final void setIndentation(String indentation) { 719 _indentation = indentation != null 720 ? indentation 721 : DEFAULT_INDENTATION; 722 723 checkInvariants(); 725 } 726 727 733 public final String getIndentation() { 734 return _indentation; 735 } 736 737 743 private void closeStartTag() 744 throws IOException { 745 _out.write('>'); 746 } 747 748 765 public final void declaration() throws IllegalStateException , IOException { 766 767 if (_state != BEFORE_XML_DECLARATION) { 769 throw new IllegalStateException ("getState() == " + _state); 770 } 771 772 _state = ERROR_STATE; 775 776 _encoder.declaration(_out); 778 779 _out.write(_lineBreakChars); 781 782 _state = BEFORE_DTD_DECLARATION; 784 785 checkInvariants(); 787 } 788 789 842 public final void dtd(String name, String publicID, String systemID) 843 throws IllegalStateException , 844 IllegalArgumentException , 845 InvalidXMLException, 846 IOException { 847 848 if (_state != BEFORE_XML_DECLARATION 850 && _state != BEFORE_DTD_DECLARATION) { 851 throw new IllegalStateException ("getState() == " + _state); 852 } 853 854 if (name == null) { 856 throw new IllegalArgumentException ("name == null"); 857 } else if (publicID != null && systemID == null) { 858 throw new IllegalArgumentException ("Found public identifier, but no system identifier."); 859 } 860 861 XMLChecker.checkName(name); 863 865 _state = ERROR_STATE; 868 869 _out.write("<!DOCTYPE "); 871 _out.write(name); 872 if (publicID != null) { 873 _out.write(" PUBLIC \""); 874 _out.write(publicID); 875 _out.write('"'); 876 _out.write(' '); 877 _out.write('"'); 878 _out.write(systemID); 879 _out.write('"'); 880 } else if (systemID != null) { 881 _out.write(" SYSTEM \""); 882 _out.write(systemID); 883 _out.write('"'); 884 } 885 closeStartTag(); 886 887 _state = BEFORE_ROOT_ELEMENT; 889 890 checkInvariants(); 892 } 893 894 916 public final void startTag(String type) 917 throws IllegalStateException , IllegalArgumentException , IOException { 918 919 if (_state != BEFORE_XML_DECLARATION && 921 _state != BEFORE_DTD_DECLARATION && 922 _state != BEFORE_ROOT_ELEMENT && 923 _state != START_TAG_OPEN && 924 _state != WITHIN_ELEMENT) { 925 throw new IllegalStateException ("getState() == " + _state); 926 927 } else if (type == null) { 929 throw new IllegalArgumentException ("type == null"); 930 } 931 932 boolean startTagOpen = _state == START_TAG_OPEN; 933 934 _state = ERROR_STATE; 937 938 if (_elementStackSize == _elementStack.length) { 940 String [] newStack; 941 try { 942 newStack = new String [(_elementStackSize + 1) * 2]; 943 } catch (OutOfMemoryError error) { 944 newStack = new String [_elementStackSize + 1]; 945 } 946 System.arraycopy(_elementStack, 0, newStack, 0, _elementStackSize); 947 _elementStack = newStack; 948 } 949 950 _elementStack[_elementStackSize] = type; 952 _elementStackSize++; 953 954 if (startTagOpen) { 957 _out.write('>'); 958 } 959 960 _out.write(_lineBreakChars); 962 writeIndentation(); 963 964 _out.write('<'); 965 966 _out.write(type); 968 969 _state = START_TAG_OPEN; 971 972 checkInvariants(); 974 } 975 976 998 public final void attribute(String name, String value) 999 throws IllegalStateException , IllegalArgumentException , IOException { 1000 1001 if (getState() != START_TAG_OPEN) { 1003 throw new IllegalStateException ("getState() == " + _state); 1004 1005 } else if (name == null || value == null) { 1007 if (name == null && value == null) { 1008 throw new IllegalArgumentException ("name == null && value == null"); 1009 } else if (name == null) { 1010 throw new IllegalArgumentException ("name == null"); 1011 } else { 1012 throw new IllegalArgumentException ("value == null"); 1013 } 1014 } 1015 1016 _state = ERROR_STATE; 1019 1020 _encoder.attribute(_out, name, value, _quotationMark, _escapeAmpersands); 1022 1023 _state = START_TAG_O
|