1 16 17 18 42 43 package org.apache.xml.serialize; 44 45 46 import java.io.IOException ; 47 import java.io.OutputStream ; 48 import java.io.Writer ; 49 import java.util.Hashtable ; 50 import java.util.Vector ; 51 52 import org.apache.xerces.dom.DOMErrorImpl; 53 import org.apache.xerces.dom.DOMLocatorImpl; 54 import org.apache.xerces.dom.DOMMessageFormatter; 55 import org.apache.xerces.util.XMLChar; 56 import org.w3c.dom.DOMImplementation ; 57 import org.w3c.dom.Document ; 58 import org.w3c.dom.DocumentFragment ; 59 import org.w3c.dom.DocumentType ; 60 import org.w3c.dom.DOMError ; 61 import org.w3c.dom.DOMErrorHandler ; 62 import org.w3c.dom.Element ; 63 import org.w3c.dom.Entity ; 64 import org.w3c.dom.NamedNodeMap ; 65 import org.w3c.dom.Node ; 66 import org.w3c.dom.Notation ; 67 import org.w3c.dom.ls.LSException ; 68 import org.w3c.dom.ls.LSSerializerFilter ; 69 import org.w3c.dom.traversal.NodeFilter; 70 import org.xml.sax.ContentHandler ; 71 import org.xml.sax.DTDHandler ; 72 import org.xml.sax.DocumentHandler ; 73 import org.xml.sax.Locator ; 74 import org.xml.sax.SAXException ; 75 import org.xml.sax.ext.DeclHandler ; 76 import org.xml.sax.ext.LexicalHandler ; 77 78 127 public abstract class BaseMarkupSerializer 128 implements ContentHandler , DocumentHandler , LexicalHandler , 129 DTDHandler , DeclHandler , DOMSerializer, Serializer 130 { 131 132 protected short features = 0xFFFFFFFF; 134 protected DOMErrorHandler fDOMErrorHandler; 135 protected final DOMErrorImpl fDOMError = new DOMErrorImpl(); 136 protected LSSerializerFilter fDOMFilter; 137 138 protected EncodingInfo _encodingInfo; 139 140 141 147 private ElementState[] _elementStates; 148 149 150 155 private int _elementStateCount; 156 157 158 162 private Vector _preRoot; 163 164 165 169 protected boolean _started; 170 171 172 177 private boolean _prepared; 178 179 180 185 protected Hashtable _prefixes; 186 187 188 191 protected String _docTypePublicId; 192 193 194 197 protected String _docTypeSystemId; 198 199 200 206 protected OutputFormat _format; 207 208 209 212 protected Printer _printer; 213 214 215 218 protected boolean _indenting; 219 220 221 protected final StringBuffer fStrBuffer = new StringBuffer (40); 222 223 226 private Writer _writer; 227 228 229 232 private OutputStream _output; 233 234 235 protected Node fCurrentNode = null; 236 237 238 239 243 244 250 protected BaseMarkupSerializer( OutputFormat format ) 251 { 252 int i; 253 254 _elementStates = new ElementState[ 10 ]; 255 for ( i = 0 ; i < _elementStates.length ; ++i ) 256 _elementStates[ i ] = new ElementState(); 257 _format = format; 258 } 259 260 261 public DocumentHandler asDocumentHandler() 262 throws IOException 263 { 264 prepare(); 265 return this; 266 } 267 268 269 public ContentHandler asContentHandler() 270 throws IOException 271 { 272 prepare(); 273 return this; 274 } 275 276 277 public DOMSerializer asDOMSerializer() 278 throws IOException 279 { 280 prepare(); 281 return this; 282 } 283 284 285 public void setOutputByteStream( OutputStream output ) 286 { 287 if ( output == null ) { 288 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 289 "ArgumentIsNull", new Object []{"output"}); 290 throw new NullPointerException (msg); 291 } 292 _output = output; 293 _writer = null; 294 reset(); 295 } 296 297 298 public void setOutputCharStream( Writer writer ) 299 { 300 if ( writer == null ) { 301 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 302 "ArgumentIsNull", new Object []{"writer"}); 303 throw new NullPointerException (msg); 304 } 305 _writer = writer; 306 _output = null; 307 reset(); 308 } 309 310 311 public void setOutputFormat( OutputFormat format ) 312 { 313 if ( format == null ) { 314 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 315 "ArgumentIsNull", new Object []{"format"}); 316 throw new NullPointerException (msg); 317 } 318 _format = format; 319 reset(); 320 } 321 322 323 public boolean reset() 324 { 325 if ( _elementStateCount > 1 ) { 326 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 327 "ResetInMiddle", null); 328 throw new IllegalStateException (msg); 329 } 330 _prepared = false; 331 fCurrentNode = null; 332 fStrBuffer.setLength(0); 333 return true; 334 } 335 336 337 protected void prepare() 338 throws IOException 339 { 340 if ( _prepared ) 341 return; 342 343 if ( _writer == null && _output == null ) { 344 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, 345 "NoWriterSupplied", null); 346 throw new IOException (msg); 347 } 348 352 _encodingInfo = _format.getEncodingInfo(); 353 354 if ( _output != null ) { 355 _writer = _encodingInfo.getWriter(_output); 356 } 357 358 if ( _format.getIndenting() ) { 359 _indenting = true; 360 _printer = new IndentPrinter( _writer, _format ); 361 } else { 362 _indenting = false; 363 _printer = new Printer( _writer, _format ); 364 } 365 366 ElementState state; 367 368 _elementStateCount = 0; 369 state = _elementStates[ 0 ]; 370 state.namespaceURI = null; 371 state.localName = null; 372 state.rawName = null; 373 state.preserveSpace = _format.getPreserveSpace(); 374 state.empty = true; 375 state.afterElement = false; 376 state.afterComment = false; 377 state.doCData = state.inCData = false; 378 state.prefixes = null; 379 380 _docTypePublicId = _format.getDoctypePublic(); 381 _docTypeSystemId = _format.getDoctypeSystem(); 382 _started = false; 383 _prepared = true; 384 } 385 386 387 388 392 393 402 public void serialize( Element elem ) 403 throws IOException 404 { 405 reset(); 406 prepare(); 407 serializeNode( elem ); 408 _printer.flush(); 409 if ( _printer.getException() != null ) 410 throw _printer.getException(); 411 } 412 413 414 423 public void serialize( DocumentFragment frag ) 424 throws IOException 425 { 426 reset(); 427 prepare(); 428 serializeNode( frag ); 429 _printer.flush(); 430 if ( _printer.getException() != null ) 431 throw _printer.getException(); 432 } 433 434 435 444 public void serialize( Document doc ) 445 throws IOException 446 { 447 reset(); 448 prepare(); 449 serializeNode( doc ); 450 serializePreRoot(); 451 _printer.flush(); 452 if ( _printer.getException() != null ) 453 throw _printer.getException(); 454 } 455 456 457 461 462 public void startDocument() 463 throws SAXException 464 { 465 try { 466 prepare(); 467 } catch ( IOException except ) { 468 throw new SAXException ( except.toString() ); 469 } 470 } 472 473 474 public void characters( char[] chars, int start, int length ) 475 throws SAXException 476 { 477 ElementState state; 478 479 try { 480 state = content(); 481 482 486 if ( state.inCData || state.doCData ) { 487 int saveIndent; 488 489 if ( ! state.inCData ) { 493 _printer.printText( "<![CDATA[" ); 494 state.inCData = true; 495 } 496 saveIndent = _printer.getNextIndent(); 497 _printer.setNextIndent( 0 ); 498 char ch; 499 final int end = start + length; 500 for ( int index = start ; index < end; ++index ) { 501 ch = chars[index]; 502 if ( ch == ']' && index + 2 < end && 503 chars[ index + 1 ] == ']' && chars[ index + 2 ] == '>' ) { 504 _printer.printText("]]]]><![CDATA[>"); 505 index +=2; 506 continue; 507 } 508 if (!XMLChar.isValid(ch)) { 509 if (++index < end) { 511 surrogates(ch, chars[index]); 512 } 513 else { 514 fatalError("The character '"+(char)ch+"' is an invalid XML character"); 515 } 516 continue; 517 } else { 518 if ( ( ch >= ' ' && _encodingInfo.isPrintable((char)ch) && ch != 0xF7 ) || 519 ch == '\n' || ch == '\r' || ch == '\t' ) { 520 _printer.printText((char)ch); 521 } else { 522 _printer.printText("]]>&#x"); 524 _printer.printText(Integer.toHexString(ch)); 525 _printer.printText(";<![CDATA["); 526 } 527 } 528 } 529 _printer.setNextIndent( saveIndent ); 530 531 } else { 532 533 int saveIndent; 534 535 if ( state.preserveSpace ) { 536 saveIndent = _printer.getNextIndent(); 541 _printer.setNextIndent( 0 ); 542 printText( chars, start, length, true, state.unescaped ); 543 _printer.setNextIndent( saveIndent ); 544 } else { 545 printText( chars, start, length, false, state.unescaped ); 546 } 547 } 548 } catch ( IOException except ) { 549 throw new SAXException ( except ); 550 } 551 } 552 553 554 public void ignorableWhitespace( char[] chars, int start, int length ) 555 throws SAXException 556 { 557 int i; 558 559 try { 560 content(); 561 562 if ( _indenting ) { 566 _printer.setThisIndent( 0 ); 567 for ( i = start ; length-- > 0 ; ++i ) 568 _printer.printText( chars[ i ] ); 569 } 570 } catch ( IOException except ) { 571 throw new SAXException ( except ); 572 } 573 } 574 575 576 public final void processingInstruction( String target, String code ) 577 throws SAXException 578 { 579 try { 580 processingInstructionIO( target, code ); 581 } catch ( IOException except ) { 582 throw new SAXException ( except ); 583 } 584 } 585 586 public void processingInstructionIO( String target, String code ) 587 throws IOException 588 { 589 int index; 590 ElementState state; 591 592 state = content(); 593 594 index = target.indexOf( "?>" ); 597 if ( index >= 0 ) 598 fStrBuffer.append( "<?" ).append( target.substring( 0, index ) ); 599 else 600 fStrBuffer.append( "<?" ).append( target ); 601 if ( code != null ) { 602 fStrBuffer.append( ' ' ); 603 index = code.indexOf( "?>" ); 604 if ( index >= 0 ) 605 fStrBuffer.append( code.substring( 0, index ) ); 606 else 607 fStrBuffer.append( code ); 608 } 609 fStrBuffer.append( "?>" ); 610 611 if ( isDocumentState() ) { 614 if ( _preRoot == null ) 615 _preRoot = new Vector (); 616 _preRoot.addElement( fStrBuffer.toString() ); 617 } else { 618 _printer.indent(); 619 printText( fStrBuffer.toString(), true, true ); 620 _printer.unindent(); 621 if ( _indenting ) 622 state.afterElement = true; 623 } 624 625 fStrBuffer.setLength(0); 626 } 627 628 629 public void comment( char[] chars, int start, int length ) 630 throws SAXException 631 { 632 try { 633 comment( new String ( chars, start, length ) ); 634 } catch ( IOException except ) { 635 throw new SAXException ( except ); 636 } 637 } 638 639 640 public void comment( String text ) 641 throws IOException 642 { 643 int index; 644 ElementState state; 645 646 if ( _format.getOmitComments() ) 647 return; 648 649 state = content(); 650 index = text.indexOf( "-->" ); 653 if ( index >= 0 ) 654 fStrBuffer.append( "<!--" ).append( text.substring( 0, index ) ).append( "-->" ); 655 else 656 fStrBuffer.append( "<!--" ).append( text ).append( "-->" ); 657 658 if ( isDocumentState() ) { 661 if ( _preRoot == null ) 662 _preRoot = new Vector (); 663 _preRoot.addElement( fStrBuffer.toString() ); 664 } else { 665 if ( _indenting && ! state.preserveSpace) 669 _printer.breakLine(); 670 _printer.indent(); 671 printText( fStrBuffer.toString(), true, true ); 672 _printer.unindent(); 673 if ( _indenting ) 674 state.afterElement = true; 675 } 676 677 fStrBuffer.setLength(0); 678 state.afterComment = true; 679 state.afterElement = false; 680 } 681 682 683 public void startCDATA() 684 { 685 ElementState state; 686 687 state = getElementState(); 688 state.doCData = true; 689 } 690 691 692 public void endCDATA() 693 { 694 ElementState state; 695 696 state = getElementState(); 697 state.doCData = false; 698 } 699 700 701 public void startNonEscaping() 702 { 703 ElementState state; 704 705 state = getElementState(); 706 state.unescaped = true; 707 } 708 709 710 public void endNonEscaping() 711 { 712 ElementState state; 713 714 state = getElementState(); 715 state.unescaped = false; 716 } 717 718 719 public void startPreserving() 720 { 721 ElementState state; 722 723 state = getElementState(); 724 state.preserveSpace = true; 725 } 726 727 728 public void endPreserving() 729 { 730 ElementState state; 731 732 state = getElementState(); 733 state.preserveSpace = false; 734 } 735 736 737 745 public void endDocument() 746 throws SAXException 747 { 748 try { 749 serializePreRoot(); 752 _printer.flush(); 754 } catch ( IOException except ) { 755 throw new SAXException ( except ); 756 } 757 } 758 759 760 public void startEntity( String name ) 761 { 762 } 764 765 766 public void endEntity( String name ) 767 { 768 } 770 771 772 public void setDocumentLocator( Locator locator ) 773 { 774 } 776 777 778 782 783 public void skippedEntity ( String name ) 784 throws SAXException 785 { 786 try { 787 endCDATA(); 788 content(); 789 _printer.printText( '&' ); 790 _printer.printText( name ); 791 _printer.printText( ';' ); 792 } catch ( IOException except ) { 793 throw new SAXException ( except ); 794 } 795 } 796 797 798 public void startPrefixMapping( String prefix, String uri ) 799 throws SAXException 800 { 801 if ( _prefixes == null ) 802 _prefixes = new Hashtable (); 803 _prefixes.put( uri, prefix == null ? "" : prefix ); 804 } 805 806 807 public void endPrefixMapping( String prefix ) 808 throws SAXException 809 { 810 } 811 812 813 817 818 public final void startDTD( String name, String publicId, String systemId ) 819 throws SAXException 820 { 821 try { 822 _printer.enterDTD(); 823 _docTypePublicId = publicId; 824 _docTypeSystemId = systemId; 825 } catch ( IOException except ) { 826 throw new SAXException ( except ); 827 } 828 } 829 830 831 public void endDTD() 832 { 833 } 835 836 837 public void elementDecl( String name, String model ) 838 throws SAXException 839 { 840 try { 841 _printer.enterDTD(); 842 _printer.printText( "<!ELEMENT " ); 843 _printer.printText( name ); 844 _printer.printText( ' ' ); 845 _printer.printText( model ); 846 _printer.printText( '>' ); 847 if ( _indenting ) 848 _printer.breakLine(); 849 } catch ( IOException except ) { 850 throw new SAXException ( except ); 851 } 852 } 853 854 855 public void attributeDecl( String eName, String aName, String type, 856 String valueDefault, String value ) 857 throws SAXException 858 { 859 try { 860 _printer.enterDTD(); 861 _printer.printText( "<!ATTLIST " ); 862 _printer.printText( eName ); 863 _printer.printText( ' ' ); 864 _printer.printText( aName ); 865 _printer.printText( ' ' ); 866 _printer.printText( type ); 867 if ( valueDefault != null ) { 868 _printer.printText( ' ' ); 869 _printer.printText( valueDefault ); 870 } 871 if ( value != null ) { 872 _printer.printText( " \"" ); 873 printEscaped( value ); 874 _printer.printText( '"' ); 875 } 876 _printer.printText( '>' ); 877 if ( _indenting ) 878 _printer.breakLine(); 879 } catch ( IOException except ) { 880 throw new SAXException ( except ); 881 } 882 } 883 884 885 public void internalEntityDecl( String name, String value ) 886 throws SAXException 887 { 888 try { 889 _printer.enterDTD(); 890 _printer.printText( "<!ENTITY " ); 891 _printer.printText( name ); 892 _printer.printText( " \"" ); 893 printEscaped( value ); 894 _printer.printText( "\">" ); 895 if ( _indenting ) 896 _printer.breakLine(); 897 } catch ( IOException except ) { 898 throw new SAXException ( except ); 899 } 900 } 901 902 903 public void externalEntityDecl( String name, String publicId, String systemId ) 904 throws SAXException 905 { 906 try { 907 _printer.enterDTD(); 908 unparsedEntityDecl( name, publicId, systemId, null ); 909 } catch ( IOException except ) { 910 throw new SAXException ( except ); 911 } 912 } 913 914 915 public void unparsedEntityDecl( String name, String publicId, 916 String systemId, String notationName ) 917 throws SAXException 918 { 919 try { 920 _printer.enterDTD(); 921 if ( publicId == null ) { 922 _printer.printText( "<!ENTITY " ); 923 _printer.printText( name ); 924 _printer.printText( " SYSTEM " ); 925 printDoctypeURL( systemId ); 926 } else { 927 _printer.printText( "<!ENTITY " ); 928 _printer.printText( name ); 929 _printer.printText( " PUBLIC " ); 930 printDoctypeURL( publicId ); 931 _printer.printText( ' ' ); 932 printDoctypeURL( systemId ); 933 } 934 if ( notationName != null ) { 935 _printer.printText( " NDATA " ); 936 _printer.printText( notationName ); 937 } 938 _printer.printText( '>' ); 939 if ( _indenting ) 940 _printer.breakLine(); 941 } catch ( IOException except ) { 942 throw new SAXException ( except ); 943 } 944 } 945 946 947 public void notationDecl( String name, String publicId, String systemId ) 948 throws SAXException 949 { 950 try { 951 _printer.enterDTD(); 952 if ( publicId != null ) { 953 _printer.printText( "<!NOTATION " ); 954 _printer.printText( name ); 955 _printer.printText( " PUBLIC " ); 956 printDoctypeURL( publicId ); 957 if ( systemId != null ) { 958 _printer.printText( ' ' ); 959 printDoctypeURL( systemId ); 960 } 961 } else { 962 _printer.printText( "<!NOTATION " ); 963 _printer.printText( name ); 964 _printer.printText( " SYSTEM " ); 965 printDoctypeURL( systemId ); 966 } 967 _printer.printText( '>' ); 968 if ( _indenting ) 969 _printer.breakLine(); 970 } catch ( IOException except ) { 971 throw new SAXException ( except ); 972 } 973 } 974 975 976 980 981 991 protected void serializeNode( Node node ) 992 throws IOException 993 { 994 fCurrentNode = node; 995 996 switch ( node.getNodeType() ) { 1000 case Node.TEXT_NODE : { 1001 String text; 1002 1003 text = node.getNodeValue(); 1004 if ( text != null ) { 1005 if (fDOMFilter !=null && 1006 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_TEXT)!= 0) { 1007 short code = fDOMFilter.acceptNode(node); 1008 switch (code) { 1009 case NodeFilter.FILTER_REJECT: 1010 case NodeFilter.FILTER_SKIP: { 1011 break; 1012 } 1013 default: { 1014 characters(text); 1015 } 1016 } 1017 } 1018 else if ( !_indenting || getElementState().preserveSpace 1019 || (text.replace('\n',' ').trim().length() != 0)) 1020 characters( text ); 1021 1022 } 1023 break; 1024 } 1025 1026 case Node.CDATA_SECTION_NODE : { 1027 String text = node.getNodeValue(); 1028 if ((features & DOMSerializerImpl.CDATA) != 0) { 1029 if (text != null) { 1030 if (fDOMFilter != null 1031 && (fDOMFilter.getWhatToShow() 1032 & NodeFilter.SHOW_CDATA_SECTION) 1033 != 0) { 1034 short code = fDOMFilter.acceptNode(node); 1035 switch (code) { 1036 case NodeFilter.FILTER_REJECT : 1037 case NodeFilter.FILTER_SKIP : 1038 { 1039 return; 1041 } 1042 default : 1043 { 1044 } 1046 } 1047 } 1048 startCDATA(); 1049 characters(text); 1050 endCDATA(); 1051 } 1052 } else { 1053 characters(text); 1055 } 1056 break; 1057 } 1058 case Node.COMMENT_NODE : { 1059 String text; 1060 1061 if ( ! _format.getOmitComments() ) { 1062 text = node.getNodeValue(); 1063 if ( text != null ) { 1064 1065 if (fDOMFilter !=null && 1066 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_COMMENT)!= 0) { 1067 short code = fDOMFilter.acceptNode(node); 1068 switch (code) { 1069 case NodeFilter.FILTER_REJECT: 1070 case NodeFilter.FILTER_SKIP: { 1071 return; 1073 } 1074 default: { 1075 } 1077 } 1078 } 1079 comment( text ); 1080 } 1081 } 1082 break; 1083 } 1084 1085 case Node.ENTITY_REFERENCE_NODE : { 1086 Node child; 1087 1088 endCDATA(); 1089 content(); 1090 1091 if (((features & DOMSerializerImpl.ENTITIES) != 0) 1092 || (node.getFirstChild() == null)) { 1093 if (fDOMFilter !=null && 1094 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ENTITY_REFERENCE)!= 0) { 1095 short code = fDOMFilter.acceptNode(node); 1096 switch (code) { 1097 case NodeFilter.FILTER_REJECT:{ 1098 return; } 1100 case NodeFilter.FILTER_SKIP: { 1101 child = node.getFirstChild(); 1102 while ( child != null ) { 1103 serializeNode( child ); 1104 child = child.getNextSibling(); 1105 } 1106 return; 1107 } 1108 1109 default: { 1110 } 1112 } 1113 } 1114 checkUnboundNamespacePrefixedNode(node); 1115 1116 _printer.printText("&"); 1117 _printer.printText(node.getNodeName()); 1118 _printer.printText(";"); 1119 } 1120 else { 1121 child = node.getFirstChild(); 1122 while ( child != null ) { 1123 serializeNode( child ); 1124 child = child.getNextSibling(); 1125 } 1126 } 1127 1128 break; 1129 } 1130 1131 case Node.PROCESSING_INSTRUCTION_NODE : { 1132 1133 if (fDOMFilter !=null && 1134 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) { 1135 short code = fDOMFilter.acceptNode(node); 1136 switch (code) { 1137 case NodeFilter.FILTER_REJECT: 1138 case NodeFilter.FILTER_SKIP: { 1139 return; } 1141 default: { } 1143 } 1144 } 1145 processingInstructionIO( node.getNodeName(), node.getNodeValue() ); 1146 break; 1147 } 1148 case Node.ELEMENT_NODE : { 1149 1150 if (fDOMFilter !=null && 1151 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ELEMENT)!= 0) { 1152 short code = fDOMFilter.acceptNode(node); 1153 switch (code) { 1154 case NodeFilter.FILTER_REJECT: { 1155 return; 1156 } 1157 case NodeFilter.FILTER_SKIP: { 1158 Node child = node.getFirstChild(); 1159 while ( child != null ) { 1160 serializeNode( child ); 1161 child = child.getNextSibling(); 1162 } 1163 return; } 1165 1166 default: { } 1168 } 1169 } 1170 serializeElement( (Element ) node ); 1171 break; 1172 } 1173 case Node.DOCUMENT_NODE : { 1174 DocumentType docType; 1175 DOMImplementation domImpl; 1176 NamedNodeMap map; 1177 Entity entity; 1178 Notation notation; 1179 int i; 1180 1181 docType = ( (Document ) node ).getDoctype(); 1184 if (docType != null) { 1185 domImpl = ( (Document ) node ).getImplementation(); 1187 try { 1188 String internal; 1189 1190 _printer.enterDTD(); 1191 _docTypePublicId = docType.getPublicId(); 1192 _docTypeSystemId = docType.getSystemId(); 1193 internal = docType.getInternalSubset(); 1194 if ( internal != null && internal.length() > 0 ) 1195 _printer.printText( internal ); 1196 endDTD(); 1197 } 1198 catch (NoSuchMethodError nsme) { 1200 Class docTypeClass = docType.getClass(); 1201 1202 String docTypePublicId = null; 1203 String docTypeSystemId = null; 1204 try { 1205 java.lang.reflect.Method getPublicId = docTypeClass.getMethod("getPublicId", (Class []) null); 1206 if (getPublicId.getReturnType().equals(String .class)) { 1207 docTypePublicId = (String )getPublicId.invoke(docType, (Object []) null); 1208 } 1209 } 1210 catch (Exception e) { 1211 } 1213 try { 1214 java.lang.reflect.Method getSystemId = docTypeClass.getMethod("getSystemId", (Class []) null); 1215 if (getSystemId.getReturnType().equals(String .class)) { 1216 docTypeSystemId = (String )getSystemId.invoke(docType, (Object []) null); 1217 } 1218 } 1219 catch (Exception e) { 1220 } 1222 _printer.enterDTD(); 1223 _docTypePublicId = docTypePublicId; 1224 _docTypeSystemId = docTypeSystemId; 1225 endDTD(); 1226 } 1227 } 1228 } 1230 case Node.DOCUMENT_FRAGMENT_NODE : { 1231 Node child; 1232 1233 child = node.getFirstChild(); 1237 while ( child != null ) { 1238 serializeNode( child ); 1239 child = child.getNextSibling(); 1240 } 1241 break; 1242 } 1243 1244 default: 1245 break; 1246 } 1247 } 1248 1249 1250 1260 protected ElementState content() 1261 throws IOException 1262 { 1263 ElementState state; 1264 1265 state = getElementState(); 1266 if ( ! isDocumentState() ) { 1267 if ( state.inCData && ! state.doCData ) { 1269 _printer.printText( "]]>" ); 1270 state.inCData = false; 1271 } 1272 if ( state.empty ) { 1276 _printer.printText( '>' ); 1277 state.empty = false; 1278 } 1279 state.afterElement = false; 1283 state.afterComment = false; 1287 } 1288 return state; 1289 } 1290 1291 1292 1304 protected void characters( String text ) 1305 throws IOException 1306 { 1307 ElementState state; 1308 1309 state = content(); 1310 1314 if ( state.inCData || state.doCData ) { 1315 int index; 1316 int saveIndent; 1317 1318 if ( ! state.inCData ) { 1322 _printer.printText("<![CDATA["); 1323 state.inCData = true; 1324 } 1325 saveIndent = _printer.getNextIndent(); 1326 _printer.setNextIndent( 0 ); 1327 printCDATAText( text); 1328 _printer.setNextIndent( saveIndent ); 1329 1330 } else { 1331 1332 int saveIndent; 1333 1334 if ( state.preserveSpace ) { 1335 saveIndent = _printer.getNextIndent(); 1340 _printer.setNextIndent( 0 ); 1341 printText( text, true, state.unescaped ); 1342 _printer.setNextIndent( saveIndent ); 1343 } else { 1344 printText( text, false, state.unescaped ); 1345 } 1346 } 1347 } 1348 1349 1350 1358 protected abstract String getEntityRef( int ch ); 1359 1360 1361 1369 protected abstract void serializeElement( Element elem ) 1370 throws IOException ; 1371 1372 1373 1384 protected void serializePreRoot() 1385 throws IOException 1386 { 1387 int i; 1388 1389 if ( _preRoot != null ) { 1390 for ( i = 0 ; i < _preRoot.size() ; ++i ) { 1391 printText( (String ) _preRoot.elementAt( i ), true, true ); 1392 if ( _indenting ) 1393 _printer.breakLine(); 1394 } 1395 _preRoot.removeAllElements(); 1396 } 1397 } 1398 1399 1400 1404 protected void printCDATAText( String text ) throws IOException { 1405 int length = text.length(); 1406 char ch; 1407 1408 for ( int index = 0 ; index < length; ++index ) { 1409 ch = text.charAt( index ); 1410 if (ch == ']' 1411 && index + 2 < length 1412 && text.charAt(index + 1) == ']' 1413 && text.charAt(index + 2) == '>') { if (fDOMErrorHandler != null) { 1415 if ((features & DOMSerializerImpl.SPLITCDATA) == 0) { 1418 String msg = DOMMessageFormatter.formatMessage( 1419 DOMMessageFormatter.SERIALIZER_DOMAIN, 1420 "EndingCDATA", 1421 null); 1422 if ((features & DOMSerializerImpl.WELLFORMED) != 0) { 1423 modifyDOMError(msg, DOMError.SEVERITY_FATAL_ERROR, "wf-invalid-character", fCurrentNode); 1425 fDOMErrorHandler.handleError(fDOMError); 1426 throw new LSException (LSException.SERIALIZE_ERR, msg); 1427 } 1428 else { 1429 modifyDOMError(msg, DOMError.SEVERITY_ERROR, "cdata-section-not-splitted", fCurrentNode); 1431 if (!fDOMErrorHandler.handleError(fDOMError)) { 1432 throw new LSException (LSException.SERIALIZE_ERR, msg); 1433 } 1434 } 1435 } else { 1436 String msg = 1438 DOMMessageFormatter.formatMessage( 1439 DOMMessageFormatter.SERIALIZER_DOMAIN, 1440 "SplittingCDATA", 1441 null); 1442 modifyDOMError( 1443 msg, 1444 DOMError.SEVERITY_WARNING, 1445 null, fCurrentNode); 1446 fDOMErrorHandler.handleError(fDOMError); 1447 } 1448 } 1449 _printer.printText("]]]]><![CDATA[>"); 1451 index += 2; 1452 continue; 1453 } 1454 1455 if (!XMLChar.isValid(ch)) { 1456 if (++index <length) { 1458 surrogates(ch, text.charAt(index)); 1459 } 1460 else { 1461 fatalError("The character '"+(char)ch+"' is an invalid XML character"); 1462 } 1463 continue; 1464 } else { 1465 if ( ( ch >= ' ' && _encodingInfo.isPrintable((char)ch) && ch != 0xF7 ) || 1466 ch == '\n' || ch == '\r' || ch == '\t' ) { 1467 _printer.printText((char)ch); 1468 } else { 1469 1470 _printer.printText("]]>&#x"); 1472 _printer.printText(Integer.toHexString(ch)); 1473 _printer.printText(";<![CDATA["); 1474 } 1475 } 1476 } 1477 } 1478 1479 1480 protected void surrogates(int high, int low) throws IOException { 1481 if (XMLChar.isHighSurrogate(high)) { 1482 if (!XMLChar.isLowSurrogate(low)) { 1483 fatalError("The character '"+(char)low+"' is an invalid XML character"); 1485 } 1486 else { 1487 int supplemental = XMLChar.supplemental((char)high, (char)low); 1488 if (!XMLChar.isValid(supplemental)) { 1489 fatalError("The character '"+(char)supplemental+"' is an invalid XML character"); 1491 } 1492 else { 1493 if (content().inCData ) { 1494 _printer.printText("]]>&#x"); 1495 _printer.printText(Integer.toHexString(supplemental)); 1496 _printer.printText(";<![CDATA["); 1497 } 1498 else { 1499 printHex(supplemental); 1500 } 1501 } 1502 } 1503 } else { 1504 fatalError("The character '"+(char)high+"' is an invalid XML character"); 1505 } 1506 1507 } 1508 1509 1522 protected void printText( char[] chars, int start, int length, 1523 boolean preserveSpace, boolean unescaped ) 1524 throws IOException 1525 { 1526 int index; 1527 char ch; 1528 1529 if ( preserveSpace ) { 1530 while ( length-- > 0 ) { 1535 ch = chars[ start ]; 1536 ++start; 1537 if ( ch == '\n' || ch == '\r' || unescaped ) 1538 _printer.printText( ch ); 1539 else 1540 printEscaped( ch ); 1541 } 1542 } else { 1543 while ( length-- > 0 ) { 1549 ch = chars[ start ]; 1550 ++start; 1551 if ( ch == ' ' || ch == '\f' || ch == '\t' || ch == '\n' || ch == '\r' ) 1552 _printer.printSpace(); 1553 else if ( unescaped ) 1554 _printer.printText( ch ); 1555 else 1556 printEscaped( ch ); 1557 } 1558 } 1559 } 1560 1561 1562 protected void printText( String text, boolean preserveSpace, boolean unescaped ) 1563 throws IOException 1564 { 1565 int index; 1566 char ch; 1567 1568 if ( preserveSpace ) { 1569 for ( index = 0 ; index < text.length() ; ++index ) { 1574 ch = text.charAt( index ); 1575 if ( ch == '\n' || ch == '\r' || unescaped ) 1576 _printer.printText( ch ); 1577 else 1578 printEscaped( ch ); 1579 } 1580 } else { 1581 for ( index = 0 ; index < text.length() ; ++index ) { 1587 ch = text.charAt( index ); 1588 if ( ch == ' ' || ch == '\f' || ch == '\t' || ch == '\n' || ch == '\r' ) 1589 _printer.printSpace(); 1590 else if ( unescaped ) 1591 _printer.printText( ch ); 1592 else 1593 printEscaped( ch ); 1594 } 1595 } 1596 } 1597 1598 1599 1606 protected void printDoctypeURL( String url ) 1607 throws IOException 1608 { 1609 int i; 1610 1611 _printer.printText( '"' ); 1612 for( i = 0 ; i < url.length() ; ++i ) { 1613 if ( url.charAt( i ) == '"' || url.charAt( i ) < 0x20 || url.charAt( i ) > 0x7F ) { 1614 _printer.printText( '%' ); 1615 _printer.printText( Integer.toHexString( url.charAt( i ) ) ); 1616 } else 1617 _printer.printText( url.charAt( i ) ); 1618 } 1619 _printer.printText( '"' ); 1620 } 1621 1622 1623 protected void printEscaped( int ch ) 1624 throws IOException 1625 { 1626 String charRef; 1627 charRef = getEntityRef( ch ); 1632 if ( charRef != null ) { 1633 _printer.printText( '&' ); 1634 _printer.printText( charRef ); 1635 _printer.printText( ';' ); 1636 } else if ( ( ch >= ' ' && _encodingInfo.isPrintable((char)ch) && ch != 0xF7 ) || 1637 ch == '\n' || ch == '\r' || ch == '\t' ) { 1638 if (ch < 0x10000) { 1641 _printer.printText((char)ch ); 1642 } else { 1643 _printer.printText((char)(((ch-0x10000)>>10)+0xd800)); 1644 _printer.printText((char)(((ch-0x10000)&0x3ff)+0xdc00)); 1645 } 1646 } else { 1647 printHex(ch); 1648 } 1649 } 1650 1651 1654 final void printHex( int ch) throws IOException { 1655 _printer.printText( "&#x" ); 1656 _printer.printText(Integer.toHexString(ch)); 1657 _printer.printText( ';' ); 1658 1659 } 1660 1661 1662 1670 protected void printEscaped( String source ) 1671 throws IOException 1672 { 1673 for ( int i = 0 ; i < source.length() ; ++i ) { 1674 int ch = source.charAt(i); 1675 if ((ch & 0xfc00) == 0xd800 && i+1 < source.length()) { 1676 int lowch = source.charAt(i+1); 1677 if ((lowch & 0xfc00) == 0xdc00) { 1678 ch = 0x10000 + ((ch-0xd800)<<10) + lowch-0xdc00; 1679 i++; 1680 } 1681 } 1682 printEscaped(ch); 1683 } 1684 } 1685 1686 1687 1691 1692 1697 protected ElementState getElementState() 1698 { 1699 return _elementStates[ _elementStateCount ]; 1700 } 1701 1702 1703 1710 protected ElementState enterElementState( String namespaceURI, String localName, 1711 String rawName, boolean preserveSpace ) 1712 { 1713 ElementState state; 1714 1715 if ( _elementStateCount + 1 == _elementStates.length ) { 1716 ElementState[] newStates; 1717 1718 newStates = new ElementState[ _elementStates.length + 10 ]; 1721 for ( int i = 0 ; i < _elementStates.length ; ++i ) 1722 newStates[ i ] = _elementStates[ i ]; 1723 for ( int i = _elementStates.length ; i < newStates.length ; ++i ) 1724 newStates[ i ] = new ElementState(); 1725 _elementStates = newStates; 1726 } 1727 1728 ++_elementStateCount; 1729 state = _elementStates[ _elementStateCount ]; 1730 state.namespaceURI = namespaceURI; 1731 state.localName = localName; 1732 state.rawName = rawName; 1733 state.preserveSpace = preserveSpace; 1734 state.empty = true; 1735 state.afterElement = false; 1736 state.afterComment = false; 1737 state.doCData = state.inCData = false; 1738 state.unescaped = false; 1739 state.prefixes = _prefixes; 1740 1741 _prefixes = null; 1742 return state; 1743 } 1744 1745 1746 1753 protected ElementState leaveElementState() 1754 { 1755 if ( _elementStateCount > 0 ) { 1756 1757 _prefixes = null; 1758 -- _elementStateCount; 1760 return _elementStates[ _elementStateCount ]; 1761 } else { 1762 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, "Internal", null); 1763 throw new IllegalStateException (msg); 1764 } 1765 } 1766 1767 1768 1775 protected boolean isDocumentState() 1776 { 1777 return _elementStateCount == 0; 1778 } 1779 1780 1781 1789 protected String getPrefix( String namespaceURI ) 1790 { 1791 String prefix; 1792 1793 if ( _prefixes != null ) { 1794 prefix = (String ) _prefixes.get( namespaceURI ); 1795 if ( prefix != null ) 1796 return prefix; 1797 } 1798 if ( _elementStateCount == 0 ) 1799 return null; 1800 else { 1801 for ( int i = _elementStateCount ; i > 0 ; --i ) { 1802 if ( _elementStates[ i ].prefixes != null ) { 1803 prefix = (String ) _elementStates[ i ].prefixes.get( namespaceURI ); 1804 if ( prefix != null ) 1805 return prefix; 1806 } 1807 } 1808 } 1809 return null; 1810 } 1811 1812 1820 protected DOMError modifyDOMError(String message, short severity, String type, Node node){ 1821 fDOMError.reset(); 1822 fDOMError.fMessage = message; 1823 fDOMError.fType = type; 1824 fDOMError.fSeverity = severity; 1825 fDOMError.fLocator = new DOMLocatorImpl(-1, -1, -1, node, null); 1826 return fDOMError; 1827 1828 } 1829 1830 1831 protected void fatalError(String message) throws IOException { 1832 if (fDOMErrorHandler != null) { 1833 modifyDOMError(message, DOMError.SEVERITY_FATAL_ERROR, null, fCurrentNode); 1834 fDOMErrorHandler.handleError(fDOMError); 1835 } 1836 else { 1837 throw new IOException (message); 1838 } 1839 } 1840 1841 1847 protected void checkUnboundNamespacePrefixedNode (Node node) throws IOException { 1848 1849 } 1850} 1851 | Popular Tags |