1 57 58 59 83 84 package org.enhydra.apache.xml.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 org.w3c.dom.DOMImplementation ; 94 import org.w3c.dom.Document ; 95 import org.w3c.dom.DocumentFragment ; 96 import org.w3c.dom.DocumentType ; 97 import org.w3c.dom.Element ; 98 import org.w3c.dom.Entity ; 99 import org.w3c.dom.NamedNodeMap ; 100 import org.w3c.dom.Node ; 101 import org.w3c.dom.Notation ; 102 import org.xml.sax.ContentHandler ; 103 import org.xml.sax.DTDHandler ; 104 import org.xml.sax.DocumentHandler ; 105 import org.xml.sax.Locator ; 106 import org.xml.sax.SAXException ; 107 import org.xml.sax.ext.DeclHandler ; 108 import org.xml.sax.ext.LexicalHandler ; 109 110 111 155 public abstract class BaseMarkupSerializer 156 implements ContentHandler , DocumentHandler , LexicalHandler , 157 DTDHandler , DeclHandler , DOMSerializer, Serializer 158 { 159 160 161 private EncodingInfo _encodingInfo; 162 163 164 170 private ElementState[] _elementStates; 171 172 173 178 private int _elementStateCount; 179 180 181 185 private Vector _preRoot; 186 187 188 192 protected boolean _started; 193 194 195 200 private boolean _prepared; 201 202 203 208 protected Hashtable _prefixes; 209 210 211 214 protected String _docTypePublicId; 215 216 217 220 protected String _docTypeSystemId; 221 222 223 229 protected OutputFormat _format; 230 231 232 235 protected Printer _printer; 236 237 238 241 protected boolean _indenting; 242 243 244 247 private Writer _writer; 248 249 250 253 private OutputStream _output; 254 255 256 260 261 266 protected BaseMarkupSerializer( OutputFormat format ) 267 { 268 int i; 269 270 _elementStates = new ElementState[ 10 ]; 271 for ( i = 0 ; i < _elementStates.length ; ++i ) 272 _elementStates[ i ] = new ElementState(); 273 _format = format; 274 } 275 276 277 public DocumentHandler asDocumentHandler() 278 throws IOException 279 { 280 prepare(); 281 return this; 282 } 283 284 285 public ContentHandler asContentHandler() 286 throws IOException 287 { 288 prepare(); 289 return this; 290 } 291 292 293 public DOMSerializer asDOMSerializer() 294 throws IOException 295 { 296 prepare(); 297 return this; 298 } 299 300 301 public void setOutputByteStream( OutputStream output ) 302 { 303 if ( output == null ) 304 throw new NullPointerException ( "SER001 Argument 'output' is null." ); 305 _output = output; 306 _writer = null; 307 reset(); 308 } 309 310 311 public void setOutputCharStream( Writer writer ) 312 { 313 if ( writer == null ) 314 throw new NullPointerException ( "SER001 Argument 'writer' is null." ); 315 _writer = writer; 316 _output = null; 317 reset(); 318 } 319 320 321 public void setOutputFormat( OutputFormat format ) 322 { 323 if ( format == null ) 324 throw new NullPointerException ( "SER001 Argument 'format' is null." ); 325 _format = format; 326 reset(); 327 } 328 329 330 public boolean reset() 331 { 332 if ( _elementStateCount > 1 ) 333 throw new IllegalStateException ( "Serializer reset in the middle of serialization" ); 334 _prepared = false; 335 return true; 336 } 337 338 339 protected void prepare() 340 throws IOException 341 { 342 if ( _prepared ) 343 return; 344 345 if ( _writer == null && _output == null ) 346 throw new IOException ( "SER002 No writer supplied for serializer" ); 347 351 _encodingInfo = _format.getEncodingInfo(); 352 353 if ( _output != null ) { 354 _writer = _encodingInfo.getWriter(_output); 355 } 356 357 if ( _format.getIndenting() ) { 358 _indenting = true; 359 _printer = new IndentPrinter( _writer, _format ); 360 } else { 361 _indenting = false; 362 _printer = new Printer( _writer, _format ); 363 } 364 365 ElementState state; 366 367 _elementStateCount = 0; 368 state = _elementStates[ 0 ]; 369 state.namespaceURI = null; 370 state.localName = null; 371 state.rawName = null; 372 state.preserveSpace = _format.getPreserveSpace(); 373 state.empty = true; 374 state.afterElement = false; 375 state.afterComment = false; 376 state.doCData = state.inCData = false; 377 state.prefixes = null; 378 379 _docTypePublicId = _format.getDoctypePublic(); 380 _docTypeSystemId = _format.getDoctypeSystem(); 381 _started = false; 382 _prepared = true; 383 } 384 385 386 387 391 392 401 public void serialize( Element elem ) 402 throws IOException 403 { 404 prepare(); 405 serializeNode( elem ); 406 _printer.flush(); 407 if ( _printer.getException() != null ) 408 throw _printer.getException(); 409 } 410 411 412 421 public void serialize( DocumentFragment frag ) 422 throws IOException 423 { 424 prepare(); 425 serializeNode( frag ); 426 _printer.flush(); 427 if ( _printer.getException() != null ) 428 throw _printer.getException(); 429 } 430 431 432 441 public void serialize( Document doc ) 442 throws IOException 443 { 444 prepare(); 445 serializeNode( doc ); 446 serializePreRoot(); 447 _printer.flush(); 448 if ( _printer.getException() != null ) 449 throw _printer.getException(); 450 } 451 452 453 457 458 public void startDocument() 459 throws SAXException 460 { 461 try { 462 prepare(); 463 } catch ( IOException except ) { 464 throw new SAXException ( except.toString() ); 465 } 466 } 468 469 470 public void characters( char[] chars, int start, int length ) 471 throws SAXException 472 { 473 ElementState state; 474 475 try { 476 state = content(); 477 478 482 if ( state.inCData || state.doCData ) { 483 int saveIndent; 484 485 if ( ! state.inCData ) { 489 _printer.printText( "<![CDATA[" ); 490 state.inCData = true; 491 } 492 saveIndent = _printer.getNextIndent(); 493 _printer.setNextIndent( 0 ); 494 for ( int index = 0 ; index < length ; ++index ) { 495 if ( index + 2 < length && chars[ index ] == ']' && 496 chars[ index + 1 ] == ']' && chars[ index + 2 ] == '>' ) { 497 498 printText( chars, start, index + 2, true, true ); 499 _printer.printText( "]]><![CDATA[" ); 500 start += index + 2; 501 length -= index + 2; 502 index = 0; 503 } 504 } 505 if ( length > 0 ) 506 printText( chars, start, length, true, true ); 507 _printer.setNextIndent( saveIndent ); 508 509 } else { 510 511 int saveIndent; 512 513 if ( state.preserveSpace ) { 514 saveIndent = _printer.getNextIndent(); 519 _printer.setNextIndent( 0 ); 520 printText( chars, start, length, true, state.unescaped ); 521 _printer.setNextIndent( saveIndent ); 522 } else { 523 printText( chars, start, length, false, state.unescaped ); 524 } 525 } 526 } catch ( IOException except ) { 527 throw new SAXException ( except ); 528 } 529 } 530 531 532 public void ignorableWhitespace( char[] chars, int start, int length ) 533 throws SAXException 534 { 535 int i; 536 537 try { 538 content(); 539 540 if ( _indenting ) { 544 _printer.setThisIndent( 0 ); 545 for ( i = start ; length-- > 0 ; ++i ) 546 _printer.printText( chars[ i ] ); 547 } 548 } catch ( IOException except ) { 549 throw new SAXException ( except ); 550 } 551 } 552 553 554 public final void processingInstruction( String target, String code ) 555 throws SAXException 556 { 557 try { 558 processingInstructionIO( target, code ); 559 } catch ( IOException except ) { 560 throw new SAXException ( except ); 561 } 562 } 563 564 public void processingInstructionIO( String target, String code ) 565 throws IOException 566 { 567 int index; 568 StringBuffer buffer; 569 ElementState state; 570 571 state = content(); 572 buffer = new StringBuffer ( 40 ); 573 574 index = target.indexOf( "?>" ); 577 if ( index >= 0 ) 578 buffer.append( "<?" ).append( target.substring( 0, index ) ); 579 else 580 buffer.append( "<?" ).append( target ); 581 if ( code != null ) { 582 buffer.append( ' ' ); 583 index = code.indexOf( "?>" ); 584 if ( index >= 0 ) 585 buffer.append( code.substring( 0, index ) ); 586 else 587 buffer.append( code ); 588 } 589 buffer.append( "?>" ); 590 591 if ( isDocumentState() ) { 594 if ( _preRoot == null ) 595 _preRoot = new Vector (); 596 _preRoot.addElement( buffer.toString() ); 597 } else { 598 _printer.indent(); 599 printText( buffer.toString(), true, true ); 600 _printer.unindent(); 601 if ( _indenting ) 602 state.afterElement = true; 603 } 604 } 605 606 607 public void comment( char[] chars, int start, int length ) 608 throws SAXException 609 { 610 try { 611 comment( new String ( chars, start, length ) ); 612 } catch ( IOException except ) { 613 throw new SAXException ( except ); 614 } 615 } 616 617 618 public void comment( String text ) 619 throws IOException 620 { 621 StringBuffer buffer; 622 int index; 623 ElementState state; 624 625 if ( _format.getOmitComments() ) 626 return; 627 628 state = content(); 629 buffer = new StringBuffer ( 40 ); 630 index = text.indexOf( "-->" ); 633 if ( index >= 0 ) 634 buffer.append( "<!--" ).append( text.substring( 0, index ) ).append( "-->" ); 635 else 636 buffer.append( "<!--" ).append( text ).append( "-->" ); 637 638 if ( isDocumentState() ) { 641 if ( _preRoot == null ) 642 _preRoot = new Vector (); 643 _preRoot.addElement( buffer.toString() ); 644 } else { 645 if ( _indenting && ! state.preserveSpace) 649 _printer.breakLine(); 650 _printer.indent(); 651 printText( buffer.toString(), true, true ); 652 _printer.unindent(); 653 if ( _indenting ) 654 state.afterElement = true; 655 } 656 state.afterComment = true; 657 state.afterElement = false; 658 } 659 660 661 public void startCDATA() 662 { 663 ElementState state; 664 665 state = getElementState(); 666 state.doCData = true; 667 } 668 669 670 public void endCDATA() 671 { 672 ElementState state; 673 674 state = getElementState(); 675 state.doCData = false; 676 } 677 678 679 public void startNonEscaping() 680 { 681 ElementState state; 682 683 state = getElementState(); 684 state.unescaped = true; 685 } 686 687 688 public void endNonEscaping() 689 { 690 ElementState state; 691 692 state = getElementState(); 693 state.unescaped = false; 694 } 695 696 697 public void startPreserving() 698 { 699 ElementState state; 700 701 state = getElementState(); 702 state.preserveSpace = true; 703 } 704 705 706 public void endPreserving() 707 { 708 ElementState state; 709 710 state = getElementState(); 711 state.preserveSpace = false; 712 } 713 714 715 723 public void endDocument() 724 throws SAXException 725 { 726 try { 727 serializePreRoot(); 730 _printer.flush(); 732 } catch ( IOException except ) { 733 throw new SAXException ( except ); 734 } 735 } 736 737 738 public void startEntity( String name ) 739 { 740 } 742 743 744 public void endEntity( String name ) 745 { 746 } 748 749 750 public void setDocumentLocator( Locator locator ) 751 { 752 } 754 755 756 760 761 public void skippedEntity ( String name ) 762 throws SAXException 763 { 764 try { 765 endCDATA(); 766 content(); 767 _printer.printText( '&' ); 768 _printer.printText( name ); 769 _printer.printText( ';' ); 770 } catch ( IOException except ) { 771 throw new SAXException ( except ); 772 } 773 } 774 775 776 public void startPrefixMapping( String prefix, String uri ) 777 throws SAXException 778 { 779 if ( _prefixes == null ) 780 _prefixes = new Hashtable (); 781 _prefixes.put( uri, prefix == null ? "" : prefix ); 782 } 783 784 785 public void endPrefixMapping( String prefix ) 786 throws SAXException 787 { 788 } 789 790 791 795 796 public final void startDTD( String name, String publicId, String systemId ) 797 throws SAXException 798 { 799 try { 800 _printer.enterDTD(); 801 _docTypePublicId = publicId; 802 _docTypeSystemId = systemId; 803 } catch ( IOException except ) { 804 throw new SAXException ( except ); 805 } 806 } 807 808 809 public void endDTD() 810 { 811 } 813 814 815 public void elementDecl( String name, String model ) 816 throws SAXException 817 { 818 try { 819 _printer.enterDTD(); 820 _printer.printText( "<!ELEMENT " ); 821 _printer.printText( name ); 822 _printer.printText( ' ' ); 823 _printer.printText( model ); 824 _printer.printText( '>' ); 825 if ( _indenting ) 826 _printer.breakLine(); 827 } catch ( IOException except ) { 828 throw new SAXException ( except ); 829 } 830 } 831 832 833 public void attributeDecl( String eName, String aName, String type, 834 String valueDefault, String value ) 835 throws SAXException 836 { 837 try { 838 _printer.enterDTD(); 839 _printer.printText( "<!ATTLIST " ); 840 _printer.printText( eName ); 841 _printer.printText( ' ' ); 842 _printer.printText( aName ); 843 _printer.printText( ' ' ); 844 _printer.printText( type ); 845 if ( valueDefault != null ) { 846 _printer.printText( ' ' ); 847 _printer.printText( valueDefault ); 848 } 849 if ( value != null ) { 850 _printer.printText( " \"" ); 851 printEscaped( value ); 852 _printer.printText( '"' ); 853 } 854 _printer.printText( '>' ); 855 if ( _indenting ) 856 _printer.breakLine(); 857 } catch ( IOException except ) { 858 throw new SAXException ( except ); 859 } 860 } 861 862 863 public void internalEntityDecl( String name, String value ) 864 throws SAXException 865 { 866 try { 867 _printer.enterDTD(); 868 _printer.printText( "<!ENTITY " ); 869 _printer.printText( name ); 870 _printer.printText( " \"" ); 871 printEscaped( value ); 872 _printer.printText( "\">" ); 873 if ( _indenting ) 874 _printer.breakLine(); 875 } catch ( IOException except ) { 876 throw new SAXException ( except ); 877 } 878 } 879 880 881 public void externalEntityDecl( String name, String publicId, String systemId ) 882 throws SAXException 883 { 884 try { 885 _printer.enterDTD(); 886 unparsedEntityDecl( name, publicId, systemId, null ); 887 } catch ( IOException except ) { 888 throw new SAXException ( except ); 889 } 890 } 891 892 893 public void unparsedEntityDecl( String name, String publicId, 894 String systemId, String notationName ) 895 throws SAXException 896 { 897 try { 898 _printer.enterDTD(); 899 if ( publicId == null ) { 900 _printer.printText( "<!ENTITY " ); 901 _printer.printText( name ); 902 _printer.printText( " SYSTEM " ); 903 printDoctypeURL( systemId ); 904 } else { 905 _printer.printText( "<!ENTITY " ); 906 _printer.printText( name ); 907 _printer.printText( " PUBLIC " ); 908 printDoctypeURL( publicId ); 909 _printer.printText( ' ' ); 910 printDoctypeURL( systemId ); 911 } 912 if ( notationName != null ) { 913 _printer.printText( " NDATA " ); 914 _printer.printText( notationName ); 915 } 916 _printer.printText( '>' ); 917 if ( _indenting ) 918 _printer.breakLine(); 919 } catch ( IOException except ) { 920 throw new SAXException ( except ); 921 } 922 } 923 924 925 public void notationDecl( String name, String publicId, String systemId ) 926 throws SAXException 927 { 928 try { 929 _printer.enterDTD(); 930 if ( publicId != null ) { 931 _printer.printText( "<!NOTATION " ); 932 _printer.printText( name ); 933 _printer.printText( " PUBLIC " ); 934 printDoctypeURL( publicId ); 935 if ( systemId != null ) { 936 _printer.printText( ' ' ); 937 printDoctypeURL( systemId ); 938 } 939 } else { 940 _printer.printText( "<!NOTATION " ); 941 _printer.printText( name ); 942 _printer.printText( " SYSTEM " ); 943 printDoctypeURL( systemId ); 944 } 945 _printer.printText( '>' ); 946 if ( _indenting ) 947 _printer.breakLine(); 948 } catch ( IOException except ) { 949 throw new SAXException ( except ); 950 } 951 } 952 953 954 958 959 969 protected void serializeNode( Node node ) 970 throws IOException 971 { 972 switch ( node.getNodeType() ) { 976 case Node.TEXT_NODE : { 977 String text; 978 979 text = node.getNodeValue(); 980 if ( text != null ) 981 if ( !_indenting || getElementState().preserveSpace 982 || (text.replace('\n',' ').trim().length() != 0)) 983 characters( text ); 984 break; 985 } 986 987 case Node.CDATA_SECTION_NODE : { 988 String text; 989 990 text = node.getNodeValue(); 991 if ( text != null ) { 992 startCDATA(); 993 characters( text ); 994 endCDATA(); 995 } 996 break; 997 } 998 999 case Node.COMMENT_NODE : { 1000 String text; 1001 1002 if ( ! _format.getOmitComments() ) { 1003 text = node.getNodeValue(); 1004 if ( text != null ) 1005 comment( text ); 1006 } 1007 break; 1008 } 1009 1010 case Node.ENTITY_REFERENCE_NODE : { 1011 Node child; 1012 1013 endCDATA(); 1014 content(); 1015 child = node.getFirstChild(); 1016 while ( child != null ) { 1017 serializeNode( child ); 1018 child = child.getNextSibling(); 1019 } 1020 break; 1021 } 1022 1023 case Node.PROCESSING_INSTRUCTION_NODE : 1024 processingInstructionIO( node.getNodeName(), node.getNodeValue() ); 1025 break; 1026 1027 case Node.ELEMENT_NODE : 1028 serializeElement( (Element ) node ); 1029 break; 1030 1031 case Node.DOCUMENT_NODE : { 1032 DocumentType docType; 1033 DOMImplementation domImpl; 1034 NamedNodeMap map; 1035 Entity entity; 1036 Notation notation; 1037 int i; 1038 1039 docType = ( (Document ) node ).getDoctype(); 1042 if (docType != null) { 1043 domImpl = ( (Document ) node ).getImplementation(); 1045 try { 1046 String internal; 1047 1048 _printer.enterDTD(); 1049 _docTypePublicId = docType.getPublicId(); 1050 _docTypeSystemId = docType.getSystemId(); 1051 internal = docType.getInternalSubset(); 1052 if ( internal != null && internal.length() > 0 ) 1053 _printer.printText( internal ); 1054 endDTD(); 1055 } 1056 catch (NoSuchMethodError nsme) { 1058 Class docTypeClass = docType.getClass(); 1059 1060 String docTypePublicId = null; 1061 String docTypeSystemId = null; 1062 try { 1063 java.lang.reflect.Method getPublicId = docTypeClass.getMethod("getPublicId", (Class [])null); 1064 if (getPublicId.getReturnType().equals(String .class)) { 1065 docTypePublicId = (String )getPublicId.invoke(docType, (Object [])null); 1066 } 1067 } 1068 catch (Exception e) { 1069 } 1071 try { 1072 java.lang.reflect.Method getSystemId = docTypeClass.getMethod("getSystemId", (Class [])null); 1073 if (getSystemId.getReturnType().equals(String .class)) { 1074 docTypeSystemId = (String )getSystemId.invoke(docType, (Object [])null); 1075 } 1076 } 1077 catch (Exception e) { 1078 } 1080 _printer.enterDTD(); 1081 _docTypePublicId = docTypePublicId; 1082 _docTypeSystemId = docTypeSystemId; 1083 endDTD(); 1084 } 1085 } 1086 } 1088 case Node.DOCUMENT_FRAGMENT_NODE : { 1089 Node child; 1090 1091 child = node.getFirstChild(); 1095 while ( child != null ) { 1096 serializeNode( child ); 1097 child = child.getNextSibling(); 1098 } 1099 break; 1100 } 1101 1102 default: 1103 break; 1104 } 1105 } 1106 1107 1108 1118 protected ElementState content() 1119 throws IOException 1120 { 1121 ElementState state; 1122 1123 state = getElementState(); 1124 if ( ! isDocumentState() ) { 1125 if ( state.inCData && ! state.doCData ) { 1127 _printer.printText( "]]>" ); 1128 state.inCData = false; 1129 } 1130 if ( state.empty ) { 1134 _printer.printText( '>' ); 1135 state.empty = false; 1136 } 1137 state.afterElement = false; 1141 state.afterComment = false; 1145 } 1146 return state; 1147 } 1148 1149 1150 1162 protected void characters( String text ) 1163 throws IOException 1164 { 1165 ElementState state; 1166 1167 state = content(); 1168 1172 if ( state.inCData || state.doCData ) { 1173 StringBuffer buffer; 1174 int index; 1175 int saveIndent; 1176 1177 buffer = new StringBuffer ( text.length() ); 1181 if ( ! state.inCData ) { 1182 buffer.append( "<![CDATA[" ); 1183 state.inCData = true; 1184 } 1185 index = text.indexOf( "]]>" ); 1186 while ( index >= 0 ) { 1187 buffer.append( text.substring( 0, index + 2 ) ).append( "]]><![CDATA[" ); 1188 text = text.substring( index + 2 ); 1189 index = text.indexOf( "]]>" ); 1190 } 1191 buffer.append( text ); 1192 saveIndent = _printer.getNextIndent(); 1193 _printer.setNextIndent( 0 ); 1194 printText( buffer.toString(), true, true ); 1195 _printer.setNextIndent( saveIndent ); 1196 1197 } else { 1198 1199 int saveIndent; 1200 1201 if ( state.preserveSpace ) { 1202 saveIndent = _printer.getNextIndent(); 1207 _printer.setNextIndent( 0 ); 1208 printText( text, true, state.unescaped ); 1209 _printer.setNextIndent( saveIndent ); 1210 } else { 1211 printText( text, false, state.unescaped ); 1212 } 1213 } 1214 } 1215 1216 1217 1225 protected abstract String getEntityRef( int ch ); 1226 1227 1228 1236 protected abstract void serializeElement( Element elem ) 1237 throws IOException ; 1238 1239 1240 1251 protected void serializePreRoot() 1252 throws IOException 1253 { 1254 int i; 1255 1256 if ( _preRoot != null ) { 1257 for ( i = 0 ; i < _preRoot.size() ; ++i ) { 1258 printText( (String ) _preRoot.elementAt( i ), true, true ); 1259 if ( _indenting ) 1260 _printer.breakLine(); 1261 } 1262 _preRoot.removeAllElements(); 1263 } 1264 } 1265 1266 1267 1271 1272 1285 protected final void printText( char[] chars, int start, int length, 1286 boolean preserveSpace, boolean unescaped ) 1287 throws IOException 1288 { 1289 int index; 1290 char ch; 1291 1292 if ( preserveSpace ) { 1293 while ( length-- > 0 ) { 1298 ch = chars[ start ]; 1299 ++start; 1300 if ( ch == '\n' || ch == '\r' || unescaped ) 1301 _printer.printText( ch ); 1302 else 1303 printEscaped( ch ); 1304 } 1305 } else { 1306 while ( length-- > 0 ) { 1312 ch = chars[ start ]; 1313 ++start; 1314 if ( ch == ' ' || ch == '\f' || ch == '\t' || ch == '\n' || ch == '\r' ) 1315 _printer.printSpace(); 1316 else if ( unescaped ) 1317 _printer.printText( ch ); 1318 else 1319 printEscaped( ch ); 1320 } 1321 } 1322 } 1323 1324 1325 protected final void printText( String text, boolean preserveSpace, boolean unescaped ) 1326 throws IOException 1327 { 1328 int index; 1329 char ch; 1330 1331 if ( preserveSpace ) { 1332 for ( index = 0 ; index < text.length() ; ++index ) { 1337 ch = text.charAt( index ); 1338 if ( ch == '\n' || ch == '\r' || unescaped ) 1339 _printer.printText( ch ); 1340 else 1341 printEscaped( ch ); 1342 } 1343 } else { 1344 for ( index = 0 ; index < text.length() ; ++index ) { 1350 ch = text.charAt( index ); 1351 if ( ch == ' ' || ch == '\f' || ch == '\t' || ch == '\n' || ch == '\r' ) 1352 _printer.printSpace(); 1353 else if ( unescaped ) 1354 _printer.printText( ch ); 1355 else 1356 printEscaped( ch ); 1357 } 1358 } 1359 } 1360 1361 1362 1369 protected void printDoctypeURL( String url ) 1370 throws IOException 1371 { 1372 int i; 1373 1374 _printer.printText( '"' ); 1375 for( i = 0 ; i < url.length() ; ++i ) { 1376 if ( url.charAt( i ) == '"' || url.charAt( i ) < 0x20 || url.charAt( i ) > 0x7F ) { 1377 _printer.printText( '%' ); 1378 _printer.printText( Integer.toHexString( url.charAt( i ) ) ); 1379 } else 1380 _printer.printText( url.charAt( i ) ); 1381 } 1382 _printer.printText( '"' ); 1383 } 1384 1385 1386 protected void printEscaped( int ch ) 1387 throws IOException 1388 { 1389 String charRef; 1390 1391 charRef = getEntityRef( ch ); 1396 if ( charRef != null ) { 1397 _printer.printText( '&' ); 1398 _printer.printText( charRef ); 1399 _printer.printText( ';' ); 1400 } else if ( ( ch >= ' ' && _encodingInfo.isPrintable(ch) && ch != 0xF7 ) || 1401 ch == '\n' || ch == '\r' || ch == '\t' ) { 1402 if (ch < 0x10000) { 1406 _printer.printText((char)ch ); 1407 } else { 1408 _printer.printText((char)(((ch-0x10000)>>10)+0xd800)); 1409 _printer.printText((char)(((ch-0x10000)&0x3ff)+0xdc00)); 1410 } 1411 1412 } else { 1413 _printer.printText( "&#x" ); 1414 _printer.printText(Integer.toHexString(ch)); 1415 _printer.printText( ';' ); 1416 } 1417 } 1418 1419 1420 1428 protected void printEscaped( String source ) 1429 throws IOException 1430 { 1431 for ( int i = 0 ; i < source.length() ; ++i ) { 1432 int ch = source.charAt(i); 1433 if ((ch & 0xfc00) == 0xd800 && i+1 < source.length()) { 1434 int lowch = source.charAt(i+1); 1435 if ((lowch & 0xfc00) == 0xdc00) { 1436 ch = 0x10000 + ((ch-0xd800)<<10) + lowch-0xdc00; 1437 i++; 1438 } 1439 } 1440 printEscaped(ch); 1441 } 1442 } 1443 1444 1445 1449 1450 1455 protected ElementState getElementState() 1456 { 1457 return _elementStates[ _elementStateCount ]; 1458 } 1459 1460 1461 1468 protected ElementState enterElementState( String namespaceURI, String localName, 1469 String rawName, boolean preserveSpace ) 1470 { 1471 ElementState state; 1472 1473 if ( _elementStateCount + 1 == _elementStates.length ) { 1474 ElementState[] newStates; 1475 1476 newStates = new ElementState[ _elementStates.length + 10 ]; 1479 for ( int i = 0 ; i < _elementStates.length ; ++i ) 1480 newStates[ i ] = _elementStates[ i ]; 1481 for ( int i = _elementStates.length ; i < newStates.length ; ++i ) 1482 newStates[ i ] = new ElementState(); 1483 _elementStates = newStates; 1484 } 1485 1486 ++_elementStateCount; 1487 state = _elementStates[ _elementStateCount ]; 1488 state.namespaceURI = namespaceURI; 1489 state.localName = localName; 1490 state.rawName = rawName; 1491 state.preserveSpace = preserveSpace; 1492 state.empty = true; 1493 state.afterElement = false; 1494 state.afterComment = false; 1495 state.doCData = state.inCData = false; 1496 state.unescaped = false; 1497 state.prefixes = _prefixes; 1498 1499 _prefixes = null; 1500 return state; 1501 } 1502 1503 1504 1511 protected ElementState leaveElementState() 1512 { 1513 if ( _elementStateCount > 0 ) { 1514 1515 _prefixes = null; 1516 -- _elementStateCount; 1518 return _elementStates[ _elementStateCount ]; 1519 } else 1520 throw new IllegalStateException ( "Internal error: element state is zero" ); 1521 } 1522 1523 1524 1531 protected boolean isDocumentState() 1532 { 1533 return _elementStateCount == 0; 1534 } 1535 1536 1537 1545 protected String getPrefix( String namespaceURI ) 1546 { 1547 String prefix; 1548 1549 if ( _prefixes != null ) { 1550 prefix = (String ) _prefixes.get( namespaceURI ); 1551 if ( prefix != null ) 1552 return prefix; 1553 } 1554 if ( _elementStateCount == 0 ) 1555 return null; 1556 else { 1557 for ( int i = _elementStateCount ; i > 0 ; --i ) { 1558 if ( _elementStates[ i ].prefixes != null ) { 1559 prefix = (String ) _elementStates[ i ].prefixes.get( namespaceURI ); 1560 if ( prefix != null ) 1561 return prefix; 1562 } 1563 } 1564 } 1565 return null; 1566 } 1567 1568 1569} 1570 | Popular Tags |