1 57 58 59 83 84 package com.sun.org.apache.xml.internal.serialize; 85 86 87 import java.io.IOException ; 88 import java.io.OutputStream ; 89 import java.io.Writer ; 90 import java.util.Hashtable ; 91 import java.util.Vector ; 92 93 import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl; 94 import com.sun.org.apache.xerces.internal.dom.DOMLocatorImpl; 95 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter; 96 import com.sun.org.apache.xerces.internal.util.XMLChar; 97 import org.w3c.dom.DOMImplementation ; 98 import org.w3c.dom.Document ; 99 import org.w3c.dom.DocumentFragment ; 100 import org.w3c.dom.DocumentType ; 101 import org.w3c.dom.DOMError ; 102 import org.w3c.dom.DOMErrorHandler ; 103 import org.w3c.dom.Element ; 104 import org.w3c.dom.Entity ; 105 import org.w3c.dom.NamedNodeMap ; 106 import org.w3c.dom.Node ; 107 import org.w3c.dom.Notation ; 108 import org.w3c.dom.ls.LSSerializerFilter ; 109 import org.w3c.dom.traversal.NodeFilter; 110 import org.xml.sax.ContentHandler ; 111 import org.xml.sax.DTDHandler ; 112 import org.xml.sax.DocumentHandler ; 113 import org.xml.sax.Locator ; 114 import org.xml.sax.SAXException ; 115 import org.xml.sax.ext.DeclHandler ; 116 import org.xml.sax.ext.LexicalHandler ; 117 118 167 public abstract class BaseMarkupSerializer 168 implements ContentHandler , DocumentHandler , LexicalHandler , 169 DTDHandler , DeclHandler , DOMSerializer, Serializer 170 { 171 172 protected short features = 0xFFFFFFFF; 174 protected DOMErrorHandler fDOMErrorHandler; 175 protected final DOMErrorImpl fDOMError = new DOMErrorImpl(); 176 protected LSSerializerFilter fDOMFilter; 177 178 protected EncodingInfo _encodingInfo; 179 180 181 187 private ElementState[] _elementStates; 188 189 190 195 private int _elementStateCount; 196 197 198 202 private Vector _preRoot; 203 204 205 209 protected boolean _started; 210 211 212 217 private boolean _prepared; 218 219 220 225 protected Hashtable _prefixes; 226 227 228 231 protected String _docTypePublicId; 232 233 234 237 protected String _docTypeSystemId; 238 239 240 246 protected OutputFormat _format; 247 248 249 252 protected Printer _printer; 253 254 255 258 protected boolean _indenting; 259 260 261 protected final StringBuffer fStrBuffer = new StringBuffer (40); 262 263 266 private Writer _writer; 267 268 269 272 private OutputStream _output; 273 274 275 protected Node fCurrentNode = null; 276 277 278 279 283 284 290 protected BaseMarkupSerializer( OutputFormat format ) 291 { 292 int i; 293 294 _elementStates = new ElementState[ 10 ]; 295 for ( i = 0 ; i < _elementStates.length ; ++i ) 296 _elementStates[ i ] = new ElementState(); 297 _format = format; 298 } 299 300 301 public DocumentHandler asDocumentHandler() 302 throws IOException 303 { 304 prepare(); 305 return this; 306 } 307 308 309 public ContentHandler asContentHandler() 310 throws IOException 311 { 312 prepare(); 313 return this; 314 } 315 316 317 public DOMSerializer asDOMSerializer() 318 throws IOException 319 { 320 prepare(); 321 return this; 322 } 323 324 325 public void setOutputByteStream( OutputStream output ) 326 { 327 if ( output == null ) { 328 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 329 "ArgumentIsNull", new Object []{"output"}); 330 throw new NullPointerException (msg); 331 } 332 _output = output; 333 _writer = null; 334 reset(); 335 } 336 337 338 public void setOutputCharStream( Writer writer ) 339 { 340 if ( writer == null ) { 341 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 342 "ArgumentIsNull", new Object []{"writer"}); 343 throw new NullPointerException (msg); 344 } 345 _writer = writer; 346 _output = null; 347 reset(); 348 } 349 350 351 public void setOutputFormat( OutputFormat format ) 352 { 353 if ( format == null ) { 354 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 355 "ArgumentIsNull", new Object []{"format"}); 356 throw new NullPointerException (msg); 357 } 358 _format = format; 359 reset(); 360 } 361 362 363 public boolean reset() 364 { 365 if ( _elementStateCount > 1 ) { 366 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 367 "ResetInMiddle", null); 368 throw new IllegalStateException (msg); 369 } 370 _prepared = false; 371 fCurrentNode = null; 372 fStrBuffer.setLength(0); 373 return true; 374 } 375 376 377 protected void prepare() 378 throws IOException 379 { 380 if ( _prepared ) 381 return; 382 383 if ( _writer == null && _output == null ) { 384 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 385 "NoWriterSupplied", null); 386 throw new IOException (msg); 387 } 388 392 _encodingInfo = _format.getEncodingInfo(); 393 394 if ( _output != null ) { 395 _writer = _encodingInfo.getWriter(_output); 396 } 397 398 if ( _format.getIndenting() ) { 399 _indenting = true; 400 _printer = new IndentPrinter( _writer, _format ); 401 } else { 402 _indenting = false; 403 _printer = new Printer( _writer, _format ); 404 } 405 406 ElementState state; 407 408 _elementStateCount = 0; 409 state = _elementStates[ 0 ]; 410 state.namespaceURI = null; 411 state.localName = null; 412 state.rawName = null; 413 state.preserveSpace = _format.getPreserveSpace(); 414 state.empty = true; 415 state.afterElement = false; 416 state.afterComment = false; 417 state.doCData = state.inCData = false; 418 state.prefixes = null; 419 420 _docTypePublicId = _format.getDoctypePublic(); 421 _docTypeSystemId = _format.getDoctypeSystem(); 422 _started = false; 423 _prepared = true; 424 } 425 426 427 428 432 433 442 public void serialize( Element elem ) 443 throws IOException 444 { 445 reset(); 446 prepare(); 447 serializeNode( elem ); 448 _printer.flush(); 449 if ( _printer.getException() != null ) 450 throw _printer.getException(); 451 } 452 453 454 463 public void serialize( DocumentFragment frag ) 464 throws IOException 465 { 466 reset(); 467 prepare(); 468 serializeNode( frag ); 469 _printer.flush(); 470 if ( _printer.getException() != null ) 471 throw _printer.getException(); 472 } 473 474 475 484 public void serialize( Document doc ) 485 throws IOException 486 { 487 reset(); 488 prepare(); 489 serializeNode( doc ); 490 serializePreRoot(); 491 _printer.flush(); 492 if ( _printer.getException() != null ) 493 throw _printer.getException(); 494 } 495 496 497 501 502 public void startDocument() 503 throws SAXException 504 { 505 try { 506 prepare(); 507 } catch ( IOException except ) { 508 throw new SAXException ( except.toString() ); 509 } 510 } 512 513 514 public void characters( char[] chars, int start, int length ) 515 throws SAXException 516 { 517 ElementState state; 518 519 try { 520 state = content(); 521 522 526 if ( state.inCData || state.doCData ) { 527 int saveIndent; 528 529 if ( ! state.inCData ) { 533 _printer.printText( "<![CDATA[" ); 534 state.inCData = true; 535 } 536 saveIndent = _printer.getNextIndent(); 537 _printer.setNextIndent( 0 ); 538 char ch; 539 for ( int index = start ; index < length ; ++index ) { 540 ch = chars[index]; 541 if ( ch == ']' && index + 2 < length && 542 chars[ index + 1 ] == ']' && chars[ index + 2 ] == '>' ) { 543 _printer.printText("]]]]><![CDATA[>"); 544 index +=2; 545 continue; 546 } 547 if (!XMLChar.isValid(ch)) { 548 if (++index <length) { 550 surrogates(ch, chars[index]); 551 } 552 else { 553 fatalError("The character '"+(char)ch+"' is an invalid XML character"); 554 } 555 continue; 556 } else { 557 if ( ( ch >= ' ' && _encodingInfo.isPrintable((char)ch) && ch != 0xF7 ) || 558 ch == '\n' || ch == '\r' || ch == '\t' ) { 559 _printer.printText((char)ch); 560 } else { 561 _printer.printText("]]>&#x"); 563 _printer.printText(Integer.toHexString(ch)); 564 _printer.printText(";<![CDATA["); 565 } 566 } 567 } 568 _printer.setNextIndent( saveIndent ); 569 570 } else { 571 572 int saveIndent; 573 574 if ( state.preserveSpace ) { 575 saveIndent = _printer.getNextIndent(); 580 _printer.setNextIndent( 0 ); 581 printText( chars, start, length, true, state.unescaped ); 582 _printer.setNextIndent( saveIndent ); 583 } else { 584 printText( chars, start, length, false, state.unescaped ); 585 } 586 } 587 } catch ( IOException except ) { 588 throw new SAXException ( except ); 589 } 590 } 591 592 593 public void ignorableWhitespace( char[] chars, int start, int length ) 594 throws SAXException 595 { 596 int i; 597 598 try { 599 content(); 600 601 if ( _indenting ) { 605 _printer.setThisIndent( 0 ); 606 for ( i = start ; length-- > 0 ; ++i ) 607 _printer.printText( chars[ i ] ); 608 } 609 } catch ( IOException except ) { 610 throw new SAXException ( except ); 611 } 612 } 613 614 615 public final void processingInstruction( String target, String code ) 616 throws SAXException 617 { 618 try { 619 processingInstructionIO( target, code ); 620 } catch ( IOException except ) { 621 throw new SAXException ( except ); 622 } 623 } 624 625 public void processingInstructionIO( String target, String code ) 626 throws IOException 627 { 628 int index; 629 ElementState state; 630 631 state = content(); 632 633 index = target.indexOf( "?>" ); 636 if ( index >= 0 ) 637 fStrBuffer.append( "<?" ).append( target.substring( 0, index ) ); 638 else 639 fStrBuffer.append( "<?" ).append( target ); 640 if ( code != null ) { 641 fStrBuffer.append( ' ' ); 642 index = code.indexOf( "?>" ); 643 if ( index >= 0 ) 644 fStrBuffer.append( code.substring( 0, index ) ); 645 else 646 fStrBuffer.append( code ); 647 } 648 fStrBuffer.append( "?>" ); 649 650 if ( isDocumentState() ) { 653 if ( _preRoot == null ) 654 _preRoot = new Vector (); 655 _preRoot.addElement( fStrBuffer.toString() ); 656 } else { 657 _printer.indent(); 658 printText( fStrBuffer.toString(), true, true ); 659 _printer.unindent(); 660 if ( _indenting ) 661 state.afterElement = true; 662 } 663 664 fStrBuffer.setLength(0); 665 } 666 667 668 public void comment( char[] chars, int start, int length ) 669 throws SAXException 670 { 671 try { 672 comment( new String ( chars, start, length ) ); 673 } catch ( IOException except ) { 674 throw new SAXException ( except ); 675 } 676 } 677 678 679 public void comment( String text ) 680 throws IOException 681 { 682 int index; 683 ElementState state; 684 685 if ( _format.getOmitComments() ) 686 return; 687 688 state = content(); 689 index = text.indexOf( "-->" ); 692 if ( index >= 0 ) 693 fStrBuffer.append( "<!--" ).append( text.substring( 0, index ) ).append( "-->" ); 694 else 695 fStrBuffer.append( "<!--" ).append( text ).append( "-->" ); 696 697 if ( isDocumentState() ) { 700 if ( _preRoot == null ) 701 _preRoot = new Vector (); 702 _preRoot.addElement( fStrBuffer.toString() ); 703 } else { 704 if ( _indenting && ! state.preserveSpace) 708 _printer.breakLine(); 709 _printer.indent(); 710 printText( fStrBuffer.toString(), true, true ); 711 _printer.unindent(); 712 if ( _indenting ) 713 state.afterElement = true; 714 } 715 716 fStrBuffer.setLength(0); 717 state.afterComment = true; 718 state.afterElement = false; 719 } 720 721 722 public void startCDATA() 723 { 724 ElementState state; 725 726 state = getElementState(); 727 state.doCData = true; 728 } 729 730 731 public void endCDATA() 732 { 733 ElementState state; 734 735 state = getElementState(); 736 state.doCData = false; 737 } 738 739 740 public void startNonEscaping() 741 { 742 ElementState state; 743 744 state = getElementState(); 745 state.unescaped = true; 746 } 747 748 749 public void endNonEscaping() 750 { 751 ElementState state; 752 753 state = getElementState(); 754 state.unescaped = false; 755 } 756 757 758 public void startPreserving() 759 { 760 ElementState state; 761 762 state = getElementState(); 763 state.preserveSpace = true; 764 } 765 766 767 public void endPreserving() 768 { 769 ElementState state; 770 771 state = getElementState(); 772 state.preserveSpace = false; 773 } 774 775 776 784 public void endDocument() 785 throws SAXException 786 { 787 try { 788 serializePreRoot(); 791 _printer.flush(); 793 } catch ( IOException except ) { 794 throw new SAXException ( except ); 795 } 796 } 797 798 799 public void startEntity( String name ) 800 { 801 } 803 804 805 public void endEntity( String name ) 806 { 807 } 809 810 811 public void setDocumentLocator( Locator locator ) 812 { 813 } 815 816 817 821 822 public void skippedEntity ( String name ) 823 throws SAXException 824 { 825 try { 826 endCDATA(); 827 content(); 828 _printer.printText( '&' ); 829 _printer.printText( name ); 830 _printer.printText( ';' ); 831 } catch ( IOException except ) { 832 throw new SAXException ( except ); 833 } 834 } 835 836 837 public void startPrefixMapping( String prefix, String uri ) 838 throws SAXException 839 { 840 if ( _prefixes == null ) 841 _prefixes = new Hashtable (); 842 _prefixes.put( uri, prefix == null ? "" : prefix ); 843 } 844 845 846 public void endPrefixMapping( String prefix ) 847 throws SAXException 848 { 849 } 850 851 852 856 857 public final void startDTD( String name, String publicId, String systemId ) 858 throws SAXException 859 { 860 try { 861 _printer.enterDTD(); 862 _docTypePublicId = publicId; 863 _docTypeSystemId = systemId; 864 } catch ( IOException except ) { 865 throw new SAXException ( except ); 866 } 867 } 868 869 870 public void endDTD() 871 { 872 } 874 875 876 public void elementDecl( String name, String model ) 877 throws SAXException 878 { 879 try { 880 _printer.enterDTD(); 881 _printer.printText( "<!ELEMENT " ); 882 _printer.printText( name ); 883 _printer.printText( ' ' ); 884 _printer.printText( model ); 885 _printer.printText( '>' ); 886 if ( _indenting ) 887 _printer.breakLine(); 888 } catch ( IOException except ) { 889 throw new SAXException ( except ); 890 } 891 } 892 893 894 public void attributeDecl( String eName, String aName, String type, 895 String valueDefault, String value ) 896 throws SAXException 897 { 898 try { 899 _printer.enterDTD(); 900 _printer.printText( "<!ATTLIST " ); 901 _printer.printText( eName ); 902 _printer.printText( ' ' ); 903 _printer.printText( aName ); 904 _printer.printText( ' ' ); 905 _printer.printText( type ); 906 if ( valueDefault != null ) { 907 _printer.printText( ' ' ); 908 _printer.printText( valueDefault ); 909 } 910 if ( value != null ) { 911 _printer.printText( " \"" ); 912 printEscaped( value ); 913 _printer.printText( '"' ); 914 } 915 _printer.printText( '>' ); 916 if ( _indenting ) 917 _printer.breakLine(); 918 } catch ( IOException except ) { 919 throw new SAXException ( except ); 920 } 921 } 922 923 924 public void internalEntityDecl( String name, String value ) 925 throws SAXException 926 { 927 try { 928 _printer.enterDTD(); 929 _printer.printText( "<!ENTITY " ); 930 _printer.printText( name ); 931 _printer.printText( " \"" ); 932 printEscaped( value ); 933 _printer.printText( "\">" ); 934 if ( _indenting ) 935 _printer.breakLine(); 936 } catch ( IOException except ) { 937 throw new SAXException ( except ); 938 } 939 } 940 941 942 public void externalEntityDecl( String name, String publicId, String systemId ) 943 throws SAXException 944 { 945 try { 946 _printer.enterDTD(); 947 unparsedEntityDecl( name, publicId, systemId, null ); 948 } catch ( IOException except ) { 949 throw new SAXException ( except ); 950 } 951 } 952 953 954 public void unparsedEntityDecl( String name, String publicId, 955 String systemId, String notationName ) 956 throws SAXException 957 { 958 try { 959 _printer.enterDTD(); 960 if ( publicId == null ) { 961 _printer.printText( "<!ENTITY " ); 962 _printer.printText( name ); 963 _printer.printText( " SYSTEM " ); 964 printDoctypeURL( systemId ); 965 } else { 966 _printer.printText( "<!ENTITY " ); 967 _printer.printText( name ); 968 _printer.printText( " PUBLIC " ); 969 printDoctypeURL( publicId ); 970 _printer.printText( ' ' ); 971 printDoctypeURL( systemId ); 972 } 973 if ( notationName != null ) { 974 _printer.printText( " NDATA " ); 975 _printer.printText( notationName ); 976 } 977 _printer.printText( '>' ); 978 if ( _indenting ) 979 _printer.breakLine(); 980 } catch ( IOException except ) { 981 throw new SAXException ( except ); 982 } 983 } 984 985 986 public void notationDecl( String name, String publicId, String systemId ) 987 throws SAXException 988 { 989 try { 990 _printer.enterDTD(); 991 if ( publicId != null ) { 992 _printer.printText( "<!NOTATION " ); 993 _printer.printText( name ); 994 _printer.printText( " PUBLIC " ); 995 printDoctypeURL( publicId ); 996 if ( systemId != null ) { 997 _printer.printText( ' ' ); 998 printDoctypeURL( systemId ); 999 } 1000 } else { 1001 _printer.printText( "<!NOTATION " ); 1002 _printer.printText( name ); 1003 _printer.printText( " SYSTEM " ); 1004 printDoctypeURL( systemId ); 1005 } 1006 _printer.printText( '>' ); 1007 if ( _indenting ) 1008 _printer.breakLine(); 1009 } catch ( IOException except ) { 1010 throw new SAXException ( except ); 1011 } 1012 } 1013 1014 1015 1019 1020 1030 protected void serializeNode( Node node ) 1031 throws IOException 1032 { 1033 fCurrentNode = node; 1034 1035 switch ( node.getNodeType() ) { 1039 case Node.TEXT_NODE : { 1040 String text; 1041 1042 text = node.getNodeValue(); 1043 if ( text != null ) { 1044 if (fDOMFilter !=null && 1045 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_TEXT)!= 0) { 1046 short code = fDOMFilter.acceptNode(node); 1047 switch (code) { 1048 case NodeFilter.FILTER_REJECT: 1049 case NodeFilter.FILTER_SKIP: { 1050 break; 1051 } 1052 default: { 1053 characters(text); 1054 } 1055 } 1056 } 1057 else if ( !_indenting || getElementState().preserveSpace 1058 || (text.replace('\n',' ').trim().length() != 0)) 1059 characters( text ); 1060 1061 } 1062 break; 1063 } 1064 1065 case Node.CDATA_SECTION_NODE : { 1066 String text = node.getNodeValue(); 1067 if ((features & DOMSerializerImpl.CDATA) != 0) { 1068 if (text != null) { 1069 if (fDOMFilter != null 1070 && (fDOMFilter.getWhatToShow() 1071 & NodeFilter.SHOW_CDATA_SECTION) 1072 != 0) { 1073 short code = fDOMFilter.acceptNode(node); 1074 switch (code) { 1075 case NodeFilter.FILTER_REJECT : 1076 case NodeFilter.FILTER_SKIP : 1077 { 1078 return; 1080 } 1081 default : 1082 { 1083 } 1085 } 1086 } 1087 startCDATA(); 1088 characters(text); 1089 endCDATA(); 1090 } 1091 } else { 1092 characters(text); 1094 } 1095 break; 1096 } 1097 case Node.COMMENT_NODE : { 1098 String text; 1099 1100 if ( ! _format.getOmitComments() ) { 1101 text = node.getNodeValue(); 1102 if ( text != null ) { 1103 1104 if (fDOMFilter !=null && 1105 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_COMMENT)!= 0) { 1106 short code = fDOMFilter.acceptNode(node); 1107 switch (code) { 1108 case NodeFilter.FILTER_REJECT: 1109 case NodeFilter.FILTER_SKIP: { 1110 return; 1112 } 1113 default: { 1114 } 1116 } 1117 } 1118 comment( text ); 1119 } 1120 } 1121 break; 1122 } 1123 1124 case Node.ENTITY_REFERENCE_NODE : { 1125 Node child; 1126 1127 endCDATA(); 1128 content(); 1129 1130 if (((features & DOMSerializerImpl.ENTITIES) != 0) 1131 || (node.getFirstChild() == null)) { 1132 if (fDOMFilter !=null && 1133 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ENTITY_REFERENCE)!= 0) { 1134 short code = fDOMFilter.acceptNode(node); 1135 switch (code) { 1136 case NodeFilter.FILTER_REJECT:{ 1137 return; } 1139 case NodeFilter.FILTER_SKIP: { 1140 child = node.getFirstChild(); 1141 while ( child != null ) { 1142 serializeNode( child ); 1143 child = child.getNextSibling(); 1144 } 1145 return; 1146 } 1147 1148 default: { 1149 } 1151 } 1152 } 1153 checkUnboundNamespacePrefixedNode(node); 1154 1155 _printer.printText("&"); 1156 _printer.printText(node.getNodeName()); 1157 _printer.printText(";"); 1158 } 1159 else { 1160 child = node.getFirstChild(); 1161 while ( child != null ) { 1162 serializeNode( child ); 1163 child = child.getNextSibling(); 1164 } 1165 } 1166 1167 break; 1168 } 1169 1170 case Node.PROCESSING_INSTRUCTION_NODE : { 1171 1172 if (fDOMFilter !=null && 1173 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) { 1174 short code = fDOMFilter.acceptNode(node); 1175 switch (code) { 1176 case NodeFilter.FILTER_REJECT: 1177 case NodeFilter.FILTER_SKIP: { 1178 return; } 1180 default: { } 1182 } 1183 } 1184 processingInstructionIO( node.getNodeName(), node.getNodeValue() ); 1185 break; 1186 } 1187 case Node.ELEMENT_NODE : { 1188 1189 if (fDOMFilter !=null && 1190 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ELEMENT)!= 0) { 1191 short code = fDOMFilter.acceptNode(node); 1192 switch (code) { 1193 case NodeFilter.FILTER_REJECT: { 1194 return; 1195 } 1196 case NodeFilter.FILTER_SKIP: { 1197 Node child = node.getFirstChild(); 1198 while ( child != null ) { 1199 serializeNode( child ); 1200 child = child.getNextSibling(); 1201 } 1202 return; } 1204 1205 default: { } 1207 } 1208 } 1209 serializeElement( (Element ) node ); 1210 break; 1211 } 1212 case Node.DOCUMENT_NODE : { 1213 DocumentType docType; 1214 DOMImplementation domImpl; 1215 NamedNodeMap map; 1216 Entity entity; 1217 Notation notation; 1218 int i; 1219 1220 docType = ( (Document ) node ).getDoctype(); 1223 if (docType != null) { 1224 domImpl = ( (Document ) node ).getImplementation(); 1226 try { 1227 String internal; 1228 1229 _printer.enterDTD(); 1230 _docTypePublicId = docType.getPublicId(); 1231 _docTypeSystemId = docType.getSystemId(); 1232 internal = docType.getInternalSubset(); 1233 if ( internal != null && internal.length() > 0 ) 1234 _printer.printText( internal ); 1235 endDTD(); 1236 } 1237 catch (NoSuchMethodError nsme) { 1239 Class docTypeClass = docType.getClass(); 1240 1241 String docTypePublicId = null; 1242 String docTypeSystemId = null; 1243 try { 1244 java.lang.reflect.Method getPublicId = docTypeClass.getMethod("getPublicId", null); 1245 if (getPublicId.getReturnType().equals(String .class)) { 1246 docTypePublicId = (String )getPublicId.invoke(docType, null); 1247 } 1248 } 1249 catch (Exception e) { 1250 } 1252 try { 1253 java.lang.reflect.Method getSystemId = docTypeClass.getMethod("getSystemId", null); 1254 if (getSystemId.getReturnType().equals(String .class)) { 1255 docTypeSystemId = (String )getSystemId.invoke(docType, null); 1256 } 1257 } 1258 catch (Exception e) { 1259 } 1261 _printer.enterDTD(); 1262 _docTypePublicId = docTypePublicId; 1263 _docTypeSystemId = docTypeSystemId; 1264 endDTD(); 1265 } 1266 } 1267 } 1269 case Node.DOCUMENT_FRAGMENT_NODE : { 1270 Node child; 1271 1272 child = node.getFirstChild(); 1276 while ( child != null ) { 1277 serializeNode( child ); 1278 child = child.getNextSibling(); 1279 } 1280 break; 1281 } 1282 1283 default: 1284 break; 1285 } 1286 } 1287 1288 1289 1299 protected ElementState content() 1300 throws IOException 1301 { 1302 ElementState state; 1303 1304 state = getElementState(); 1305 if ( ! isDocumentState() ) { 1306 if ( state.inCData && ! state.doCData ) { 1308 _printer.printText( "]]>" ); 1309 state.inCData = false; 1310 } 1311 if ( state.empty ) { 1315 _printer.printText( '>' ); 1316 state.empty = false; 1317 } 1318 state.afterElement = false; 1322 state.afterComment = false; 1326 } 1327 return state; 1328 } 1329 1330 1331 1343 protected void characters( String text ) 1344 throws IOException 1345 { 1346 ElementState state; 1347 1348 state = content(); 1349 1353 if ( state.inCData || state.doCData ) { 1354 int index; 1355 int saveIndent; 1356 1357 if ( ! state.inCData ) { 1361 _printer.printText("<![CDATA["); 1362 state.inCData = true; 1363 } 1364 saveIndent = _printer.getNextIndent(); 1365 _printer.setNextIndent( 0 ); 1366 printCDATAText( text); 1367 _printer.setNextIndent( saveIndent ); 1368 1369 } else { 1370 1371 int saveIndent; 1372 1373 if ( state.preserveSpace ) { 1374 saveIndent = _printer.getNextIndent(); 1379 _printer.setNextIndent( 0 ); 1380 printText( text, true, state.unescaped ); 1381 _printer.setNextIndent( saveIndent ); 1382 } else { 1383 printText( text, false, state.unescaped ); 1384 } 1385 } 1386 } 1387 1388 1389 1397 protected abstract String getEntityRef( int ch ); 1398 1399 1400 1408 protected abstract void serializeElement( Element elem ) 1409 throws IOException ; 1410 1411 1412 1423 protected void serializePreRoot() 1424 throws IOException 1425 { 1426 int i; 1427 1428 if ( _preRoot != null ) { 1429 for ( i = 0 ; i < _preRoot.size() ; ++i ) { 1430 printText( (String ) _preRoot.elementAt( i ), true, true ); 1431 if ( _indenting ) 1432 _printer.breakLine(); 1433 } 1434 _preRoot.removeAllElements(); 1435 } 1436 } 1437 1438 1439 1443 protected void printCDATAText( String text ) throws IOException { 1444 int length = text.length(); 1445 char ch; 1446 1447 for ( int index = 0 ; index < length; ++index ) { 1448 ch = text.charAt( index ); 1449 if (ch == ']' 1450 && index + 2 < length 1451 && text.charAt(index + 1) == ']' 1452 && text.charAt(index + 2) == '>') { if (fDOMErrorHandler != null) { 1454 if ((features & DOMSerializerImpl.SPLITCDATA) == 0 1457 && (features & DOMSerializerImpl.WELLFORMED) == 0) { 1458 String msg = 1460 DOMMessageFormatter.formatMessage( 1461 DOMMessageFormatter.SERIALIZER_DOMAIN, 1462 "EndingCDATA", 1463 null); 1464 modifyDOMError( 1465 msg, 1466 DOMError.SEVERITY_FATAL_ERROR, 1467 fCurrentNode); 1468 boolean continueProcess = 1469 fDOMErrorHandler.handleError(fDOMError); 1470 if (!continueProcess) { 1471 throw new IOException (); 1472 } 1473 } else { 1474 String msg = 1476 DOMMessageFormatter.formatMessage( 1477 DOMMessageFormatter.SERIALIZER_DOMAIN, 1478 "SplittingCDATA", 1479 null); 1480 modifyDOMError( 1481 msg, 1482 DOMError.SEVERITY_WARNING, 1483 fCurrentNode); 1484 fDOMErrorHandler.handleError(fDOMError); 1485 } 1486 } 1487 _printer.printText("]]]]><![CDATA[>"); 1489 index += 2; 1490 continue; 1491 } 1492 1493 if (!XMLChar.isValid(ch)) { 1494 if (++index <length) { 1496 surrogates(ch, text.charAt(index)); 1497 } 1498 else { 1499 fatalError("The character '"+(char)ch+"' is an invalid XML character"); 1500 } 1501 continue; 1502 } else { 1503 if ( ( ch >= ' ' && _encodingInfo.isPrintable((char)ch) && ch != 0xF7 ) || 1504 ch == '\n' || ch == '\r' || ch == '\t' ) { 1505 _printer.printText((char)ch); 1506 } else { 1507 1508 _printer.printText("]]>&#x"); 1510 _printer.printText(Integer.toHexString(ch)); 1511 _printer.printText(";<![CDATA["); 1512 } 1513 } 1514 } 1515 } 1516 1517 1518 protected void surrogates(int high, int low) throws IOException { 1519 if (XMLChar.isHighSurrogate(high)) { 1520 if (!XMLChar.isLowSurrogate(low)) { 1521 fatalError("The character '"+(char)low+"' is an invalid XML character"); 1523 } 1524 else { 1525 int supplemental = XMLChar.supplemental((char)high, (char)low); 1526 if (!XMLChar.isValid(supplemental)) { 1527 fatalError("The character '"+(char)supplemental+"' is an invalid XML character"); 1529 } 1530 else { 1531 if (content().inCData ) { 1532 _printer.printText("]]>&#x"); 1533 _printer.printText(Integer.toHexString(supplemental)); 1534 _printer.printText(";<![CDATA["); 1535 } 1536 else { 1537 printHex(supplemental); 1538 } 1539 } 1540 } 1541 } else { 1542 fatalError("The character '"+(char)high+"' is an invalid XML character"); 1543 } 1544 1545 } 1546 1547 1560 protected void printText( char[] chars, int start, int length, 1561 boolean preserveSpace, boolean unescaped ) 1562 throws IOException 1563 { 1564 int index; 1565 char ch; 1566 1567 if ( preserveSpace ) { 1568 while ( length-- > 0 ) { 1573 ch = chars[ start ]; 1574 ++start; 1575 if ( ch == '\n' || ch == '\r' || unescaped ) 1576 _printer.printText( ch ); 1577 else 1578 printEscaped( ch ); 1579 } 1580 } else { 1581 while ( length-- > 0 ) { 1587 ch = chars[ start ]; 1588 ++start; 1589 if ( ch == ' ' || ch == '\f' || ch == '\t' || ch == '\n' || ch == '\r' ) 1590 _printer.printSpace(); 1591 else if ( unescaped ) 1592 _printer.printText( ch ); 1593 else 1594 printEscaped( ch ); 1595 } 1596 } 1597 } 1598 1599 1600 protected void printText( String text, boolean preserveSpace, boolean unescaped ) 1601 throws IOException 1602 { 1603 int index; 1604 char ch; 1605 1606 if ( preserveSpace ) { 1607 for ( index = 0 ; index < text.length() ; ++index ) { 1612 ch = text.charAt( index ); 1613 if ( ch == '\n' || ch == '\r' || unescaped ) 1614 _printer.printText( ch ); 1615 else 1616 printEscaped( ch ); 1617 } 1618 } else { 1619 for ( index = 0 ; index < text.length() ; ++index ) { 1625 ch = text.charAt( index ); 1626 if ( ch == ' ' || ch == '\f' || ch == '\t' || ch == '\n' || ch == '\r' ) 1627 _printer.printSpace(); 1628 else if ( unescaped ) 1629 _printer.printText( ch ); 1630 else 1631 printEscaped( ch ); 1632 } 1633 } 1634 } 1635 1636 1637 1644 protected void printDoctypeURL( String url ) 1645 throws IOException 1646 { 1647 int i; 1648 1649 _printer.printText( '"' ); 1650 for( i = 0 ; i < url.length() ; ++i ) { 1651 if ( url.charAt( i ) == '"' || url.charAt( i ) < 0x20 || url.charAt( i ) > 0x7F ) { 1652 _printer.printText( '%' ); 1653 _printer.printText( Integer.toHexString( url.charAt( i ) ) ); 1654 } else 1655 _printer.printText( url.charAt( i ) ); 1656 } 1657 _printer.printText( '"' ); 1658 } 1659 1660 1661 protected void printEscaped( int ch ) 1662 throws IOException 1663 { 1664 String charRef; 1665 charRef = getEntityRef( ch ); 1670 if ( charRef != null ) { 1671 _printer.printText( '&' ); 1672 _printer.printText( charRef ); 1673 _printer.printText( ';' ); 1674 } else if ( ( ch >= ' ' && _encodingInfo.isPrintable((char)ch) && ch != 0xF7 ) || 1675 ch == '\n' || ch == '\r' || ch == '\t' ) { 1676 if (ch < 0x10000) { 1679 _printer.printText((char)ch ); 1680 } else { 1681 _printer.printText((char)(((ch-0x10000)>>10)+0xd800)); 1682 _printer.printText((char)(((ch-0x10000)&0x3ff)+0xdc00)); 1683 } 1684 } else { 1685 printHex(ch); 1686 } 1687 } 1688 1689 1692 final void printHex( int ch) throws IOException { 1693 _printer.printText( "&#x" ); 1694 _printer.printText(Integer.toHexString(ch)); 1695 _printer.printText( ';' ); 1696 1697 } 1698 1699 1700 1708 protected void printEscaped( String source ) 1709 throws IOException 1710 { 1711 for ( int i = 0 ; i < source.length() ; ++i ) { 1712 int ch = source.charAt(i); 1713 if ((ch & 0xfc00) == 0xd800 && i+1 < source.length()) { 1714 int lowch = source.charAt(i+1); 1715 if ((lowch & 0xfc00) == 0xdc00) { 1716 ch = 0x10000 + ((ch-0xd800)<<10) + lowch-0xdc00; 1717 i++; 1718 } 1719 } 1720 printEscaped(ch); 1721 } 1722 } 1723 1724 1725 1729 1730 1735 protected ElementState getElementState() 1736 { 1737 return _elementStates[ _elementStateCount ]; 1738 } 1739 1740 1741 1748 protected ElementState enterElementState( String namespaceURI, String localName, 1749 String rawName, boolean preserveSpace ) 1750 { 1751 ElementState state; 1752 1753 if ( _elementStateCount + 1 == _elementStates.length ) { 1754 ElementState[] newStates; 1755 1756 newStates = new ElementState[ _elementStates.length + 10 ]; 1759 for ( int i = 0 ; i < _elementStates.length ; ++i ) 1760 newStates[ i ] = _elementStates[ i ]; 1761 for ( int i = _elementStates.length ; i < newStates.length ; ++i ) 1762 newStates[ i ] = new ElementState(); 1763 _elementStates = newStates; 1764 } 1765 1766 ++_elementStateCount; 1767 state = _elementStates[ _elementStateCount ]; 1768 state.namespaceURI = namespaceURI; 1769 state.localName = localName; 1770 state.rawName = rawName; 1771 state.preserveSpace = preserveSpace; 1772 state.empty = true; 1773 state.afterElement = false; 1774 state.afterComment = false; 1775 state.doCData = state.inCData = false; 1776 state.unescaped = false; 1777 state.prefixes = _prefixes; 1778 1779 _prefixes = null; 1780 return state; 1781 } 1782 1783 1784 1791 protected ElementState leaveElementState() 1792 { 1793 if ( _elementStateCount > 0 ) { 1794 1795 _prefixes = null; 1796 -- _elementStateCount; 1798 return _elementStates[ _elementStateCount ]; 1799 } else { 1800 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, "Internal", null); 1801 throw new IllegalStateException (msg); 1802 } 1803 } 1804 1805 1806 1813 protected boolean isDocumentState() 1814 { 1815 return _elementStateCount == 0; 1816 } 1817 1818 1819 1827 protected String getPrefix( String namespaceURI ) 1828 { 1829 String prefix; 1830 1831 if ( _prefixes != null ) { 1832 prefix = (String ) _prefixes.get( namespaceURI ); 1833 if ( prefix != null ) 1834 return prefix; 1835 } 1836 if ( _elementStateCount == 0 ) 1837 return null; 1838 else { 1839 for ( int i = _elementStateCount ; i > 0 ; --i ) { 1840 if ( _elementStates[ i ].prefixes != null ) { 1841 prefix = (String ) _elementStates[ i ].prefixes.get( namespaceURI ); 1842 if ( prefix != null ) 1843 return prefix; 1844 } 1845 } 1846 } 1847 return null; 1848 } 1849 1850 1857 protected DOMError modifyDOMError(String message, short severity, Node node){ 1858 fDOMError.reset(); 1859 fDOMError.fMessage = message; 1860 fDOMError.fSeverity = severity; 1861 fDOMError.fLocator = new DOMLocatorImpl(-1, -1, -1, node, null); 1862 return fDOMError; 1863 1864 } 1865 1866 1867 protected void fatalError(String message) throws IOException { 1868 if (fDOMErrorHandler != null) { 1869 modifyDOMError(message, DOMError.SEVERITY_FATAL_ERROR, fCurrentNode); 1870 fDOMErrorHandler.handleError(fDOMError); 1871 } 1872 else { 1873 throw new IOException (message); 1874 } 1875 } 1876 1877 1883 protected void checkUnboundNamespacePrefixedNode (Node node) throws IOException { 1884 1885 } 1886} 1887 | Popular Tags |