1 16 17 18 19 32 33 package org.apache.xml.serialize; 34 35 36 import java.io.IOException ; 37 import java.io.OutputStream ; 38 import java.io.Writer ; 39 import java.util.Enumeration ; 40 41 import org.apache.xerces.dom.DOMMessageFormatter; 42 import org.apache.xerces.util.NamespaceSupport; 43 import org.apache.xerces.util.SymbolTable; 44 import org.apache.xerces.util.XMLChar; 45 import org.apache.xerces.util.XMLSymbols; 46 import org.apache.xerces.xni.NamespaceContext; 47 import org.w3c.dom.Attr ; 48 import org.w3c.dom.DOMError ; 49 import org.w3c.dom.Element ; 50 import org.w3c.dom.NamedNodeMap ; 51 import org.w3c.dom.Node ; 52 import org.w3c.dom.traversal.NodeFilter; 53 import org.xml.sax.AttributeList ; 54 import org.xml.sax.Attributes ; 55 import org.xml.sax.SAXException ; 56 import org.xml.sax.helpers.AttributesImpl ; 57 58 90 public class XMLSerializer 91 extends BaseMarkupSerializer { 92 93 97 protected static final boolean DEBUG = false; 98 99 103 107 108 protected NamespaceSupport fNSBinder; 109 110 111 protected NamespaceSupport fLocalNSBinder; 112 113 114 protected SymbolTable fSymbolTable; 115 116 protected final static String PREFIX = "NS"; 117 118 125 protected boolean fNamespaces = false; 126 127 130 protected boolean fNamespacePrefixes = true; 131 132 133 private boolean fPreserveSpace; 134 135 136 141 public XMLSerializer() { 142 super( new OutputFormat( Method.XML, null, false ) ); 143 } 144 145 146 151 public XMLSerializer( OutputFormat format ) { 152 super( format != null ? format : new OutputFormat( Method.XML, null, false ) ); 153 _format.setMethod( Method.XML ); 154 } 155 156 157 165 public XMLSerializer( Writer writer, OutputFormat format ) { 166 super( format != null ? format : new OutputFormat( Method.XML, null, false ) ); 167 _format.setMethod( Method.XML ); 168 setOutputCharStream( writer ); 169 } 170 171 172 180 public XMLSerializer( OutputStream output, OutputFormat format ) { 181 super( format != null ? format : new OutputFormat( Method.XML, null, false ) ); 182 _format.setMethod( Method.XML ); 183 setOutputByteStream( output ); 184 } 185 186 187 public void setOutputFormat( OutputFormat format ) { 188 super.setOutputFormat( format != null ? format : new OutputFormat( Method.XML, null, false ) ); 189 } 190 191 192 199 public void setNamespaces (boolean namespaces){ 200 fNamespaces = namespaces; 201 if (fNSBinder == null) { 202 fNSBinder = new NamespaceSupport(); 203 fLocalNSBinder = new NamespaceSupport(); 204 fSymbolTable = new SymbolTable(); 205 } 206 } 207 208 212 213 public void startElement( String namespaceURI, String localName, 214 String rawName, Attributes attrs ) 215 throws SAXException 216 { 217 int i; 218 boolean preserveSpace; 219 ElementState state; 220 String name; 221 String value; 222 boolean addNSAttr = false; 223 224 if (DEBUG) { 225 System.out.println("==>startElement("+namespaceURI+","+localName+ 226 ","+rawName+")"); 227 } 228 229 try { 230 if (_printer == null) { 231 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, "NoWriterSupplied", null); 232 throw new IllegalStateException (msg); 233 } 234 235 state = getElementState(); 236 if (isDocumentState()) { 237 if (! _started) 242 startDocument( ( localName == null || localName.length() == 0 ) ? rawName : localName ); 243 } else { 244 if (state.empty) 248 _printer.printText( '>' ); 249 if (state.inCData) { 251 _printer.printText( "]]>" ); 252 state.inCData = false; 253 } 254 if (_indenting && ! state.preserveSpace && 258 ( state.empty || state.afterElement || state.afterComment)) 259 _printer.breakLine(); 260 } 261 preserveSpace = state.preserveSpace; 262 263 attrs = extractNamespaces(attrs); 266 267 if (rawName == null || rawName.length() == 0) { 270 if (localName == null) { 271 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, "NoName", null); 272 throw new SAXException (msg); 273 } 274 if (namespaceURI != null && ! namespaceURI.equals( "" )) { 275 String prefix; 276 prefix = getPrefix( namespaceURI ); 277 if (prefix != null && prefix.length() > 0) 278 rawName = prefix + ":" + localName; 279 else 280 rawName = localName; 281 } else 282 rawName = localName; 283 addNSAttr = true; 284 } 285 286 _printer.printText( '<' ); 287 _printer.printText( rawName ); 288 _printer.indent(); 289 290 if (attrs != null) { 294 for (i = 0 ; i < attrs.getLength() ; ++i) { 295 _printer.printSpace(); 296 297 name = attrs.getQName( i ); 298 if (name != null && name.length() == 0) { 299 String prefix; 300 String attrURI; 301 302 name = attrs.getLocalName( i ); 303 attrURI = attrs.getURI( i ); 304 if (( attrURI != null && attrURI.length() != 0 ) && 305 ( namespaceURI == null || namespaceURI.length() == 0 || 306 ! attrURI.equals( namespaceURI ) )) { 307 prefix = getPrefix( attrURI ); 308 if (prefix != null && prefix.length() > 0) 309 name = prefix + ":" + name; 310 } 311 } 312 313 value = attrs.getValue( i ); 314 if (value == null) 315 value = ""; 316 _printer.printText( name ); 317 _printer.printText( "=\"" ); 318 printEscaped( value ); 319 _printer.printText( '"' ); 320 321 if (name.equals( "xml:space" )) { 325 if (value.equals( "preserve" )) 326 preserveSpace = true; 327 else 328 preserveSpace = _format.getPreserveSpace(); 329 } 330 } 331 } 332 333 if (_prefixes != null) { 334 Enumeration keys; 335 336 keys = _prefixes.keys(); 337 while (keys.hasMoreElements()) { 338 _printer.printSpace(); 339 value = (String ) keys.nextElement(); 340 name = (String ) _prefixes.get( value ); 341 if (name.length() == 0) { 342 _printer.printText( "xmlns=\"" ); 343 printEscaped( value ); 344 _printer.printText( '"' ); 345 } else { 346 _printer.printText( "xmlns:" ); 347 _printer.printText( name ); 348 _printer.printText( "=\"" ); 349 printEscaped( value ); 350 _printer.printText( '"' ); 351 } 352 } 353 } 354 355 state = enterElementState( namespaceURI, localName, rawName, preserveSpace ); 359 name = ( localName == null || localName.length() == 0 ) ? rawName : namespaceURI + "^" + localName; 360 state.doCData = _format.isCDataElement( name ); 361 state.unescaped = _format.isNonEscapingElement( name ); 362 } catch (IOException except) { 363 throw new SAXException ( except ); 364 } 365 } 366 367 368 public void endElement( String namespaceURI, String localName, 369 String rawName ) 370 throws SAXException 371 { 372 try { 373 endElementIO( namespaceURI, localName, rawName ); 374 } catch (IOException except) { 375 throw new SAXException ( except ); 376 } 377 } 378 379 380 public void endElementIO( String namespaceURI, String localName, 381 String rawName ) 382 throws IOException 383 { 384 ElementState state; 385 if (DEBUG) { 386 System.out.println("==>endElement: " +rawName); 387 } 388 _printer.unindent(); 392 state = getElementState(); 393 if (state.empty) { 394 _printer.printText( "/>" ); 395 } else { 396 if (state.inCData) 398 _printer.printText( "]]>" ); 399 if (_indenting && ! state.preserveSpace && (state.afterElement || state.afterComment)) 403 _printer.breakLine(); 404 _printer.printText( "</" ); 405 _printer.printText( state.rawName ); 406 _printer.printText( '>' ); 407 } 408 state = leaveElementState(); 411 state.afterElement = true; 412 state.afterComment = false; 413 state.empty = false; 414 if (isDocumentState()) 415 _printer.flush(); 416 } 417 418 419 423 424 public void startElement( String tagName, AttributeList attrs ) 425 throws SAXException 426 { 427 int i; 428 boolean preserveSpace; 429 ElementState state; 430 String name; 431 String value; 432 433 434 if (DEBUG) { 435 System.out.println("==>startElement("+tagName+")"); 436 } 437 438 try { 439 if (_printer == null) { 440 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.SERIALIZER_DOMAIN, "NoWriterSupplied", null); 441 throw new IllegalStateException (msg); 442 } 443 444 state = getElementState(); 445 if (isDocumentState()) { 446 if (! _started) 451 startDocument( tagName ); 452 } else { 453 if (state.empty) 457 _printer.printText( '>' ); 458 if (state.inCData) { 460 _printer.printText( "]]>" ); 461 state.inCData = false; 462 } 463 if (_indenting && ! state.preserveSpace && 467 ( state.empty || state.afterElement || state.afterComment)) 468 _printer.breakLine(); 469 } 470 preserveSpace = state.preserveSpace; 471 472 475 _printer.printText( '<' ); 476 _printer.printText( tagName ); 477 _printer.indent(); 478 479 if (attrs != null) { 483 for (i = 0 ; i < attrs.getLength() ; ++i) { 484 _printer.printSpace(); 485 name = attrs.getName( i ); 486 value = attrs.getValue( i ); 487 if (value != null) { 488 _printer.printText( name ); 489 _printer.printText( "=\"" ); 490 printEscaped( value ); 491 _printer.printText( '"' ); 492 } 493 494 if (name.equals( "xml:space" )) { 498 if (value.equals( "preserve" )) 499 preserveSpace = true; 500 else 501 preserveSpace = _format.getPreserveSpace(); 502 } 503 } 504 } 505 state = enterElementState( null, null, tagName, preserveSpace ); 509 state.doCData = _format.isCDataElement( tagName ); 510 state.unescaped = _format.isNonEscapingElement( tagName ); 511 } catch (IOException except) { 512 throw new SAXException ( except ); 513 } 514 515 } 516 517 518 public void endElement( String tagName ) 519 throws SAXException 520 { 521 endElement( null, null, tagName ); 522 } 523 524 525 526 530 531 543 protected void startDocument( String rootTagName ) 544 throws IOException 545 { 546 int i; 547 String dtd; 548 549 dtd = _printer.leaveDTD(); 550 if (! _started) { 551 552 if (! _format.getOmitXMLDeclaration()) { 553 StringBuffer buffer; 554 555 buffer = new StringBuffer ( "<?xml version=\"" ); 558 if (_format.getVersion() != null) 559 buffer.append( _format.getVersion() ); 560 else 561 buffer.append( "1.0" ); 562 buffer.append( '"' ); 563 String format_encoding = _format.getEncoding(); 564 if (format_encoding != null) { 565 buffer.append( " encoding=\"" ); 566 buffer.append( format_encoding ); 567 buffer.append( '"' ); 568 } 569 if (_format.getStandalone() && _docTypeSystemId == null && 570 _docTypePublicId == null) 571 buffer.append( " standalone=\"yes\"" ); 572 buffer.append( "?>" ); 573 _printer.printText( buffer ); 574 _printer.breakLine(); 575 } 576 577 if (! _format.getOmitDocumentType()) { 578 if (_docTypeSystemId != null) { 579 _printer.printText( "<!DOCTYPE " ); 583 _printer.printText( rootTagName ); 584 if (_docTypePublicId != null) { 585 _printer.printText( " PUBLIC " ); 586 printDoctypeURL( _docTypePublicId ); 587 if (_indenting) { 588 _printer.breakLine(); 589 for (i = 0 ; i < 18 + rootTagName.length() ; ++i) 590 _printer.printText( " " ); 591 } else 592 _printer.printText( " " ); 593 printDoctypeURL( _docTypeSystemId ); 594 } else { 595 _printer.printText( " SYSTEM " ); 596 printDoctypeURL( _docTypeSystemId ); 597 } 598 599 if (dtd != null && dtd.length() > 0) { 602 _printer.printText( " [" ); 603 printText( dtd, true, true ); 604 _printer.printText( ']' ); 605 } 606 607 _printer.printText( ">" ); 608 _printer.breakLine(); 609 } else if (dtd != null && dtd.length() > 0) { 610 _printer.printText( "<!DOCTYPE " ); 611 _printer.printText( rootTagName ); 612 _printer.printText( " [" ); 613 printText( dtd, true, true ); 614 _printer.printText( "]>" ); 615 _printer.breakLine(); 616 } 617 } 618 } 619 _started = true; 620 serializePreRoot(); 622 } 623 624 625 630 protected void serializeElement( Element elem ) 631 throws IOException 632 { 633 Attr attr; 634 NamedNodeMap attrMap; 635 int i; 636 Node child; 637 ElementState state; 638 String name; 639 String value; 640 String tagName; 641 642 String prefix, localUri; 643 String uri; 644 if (fNamespaces) { 645 fLocalNSBinder.reset(); 649 650 fNSBinder.pushContext(); 652 } 653 654 if (DEBUG) { 655 System.out.println("==>startElement: " +elem.getNodeName() +" ns="+elem.getNamespaceURI()); 656 } 657 tagName = elem.getTagName(); 658 state = getElementState(); 659 if (isDocumentState()) { 660 665 if (! _started) { 666 startDocument( tagName); 667 } 668 } else { 669 if (state.empty) 673 _printer.printText( '>' ); 674 if (state.inCData) { 676 _printer.printText( "]]>" ); 677 state.inCData = false; 678 } 679 if (_indenting && ! state.preserveSpace && 683 ( state.empty || state.afterElement || state.afterComment)) 684 _printer.breakLine(); 685 } 686 687 fPreserveSpace = state.preserveSpace; 690 691 692 int length = 0; 693 attrMap = null; 694 if (elem.hasAttributes()) { 696 attrMap = elem.getAttributes(); 697 length = attrMap.getLength(); 698 } 699 700 if (!fNamespaces) { 702 _printer.printText( '<' ); 704 _printer.printText( tagName ); 705 _printer.indent(); 706 707 for ( i = 0 ; i < length ; ++i ) { 711 attr = (Attr ) attrMap.item( i ); 712 name = attr.getName(); 713 value = attr.getValue(); 714 if ( value == null ) 715 value = ""; 716 printAttribute (name, value, attr.getSpecified(), attr); 717 } 718 } else { 720 724 729 for (i = 0;i < length;i++) { 730 731 attr = (Attr ) attrMap.item( i ); 732 uri = attr.getNamespaceURI(); 733 if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) { 735 736 value = attr.getNodeValue(); 737 if (value == null) { 738 value=XMLSymbols.EMPTY_STRING; 739 } 740 741 if (value.equals(NamespaceContext.XMLNS_URI)) { 742 if (fDOMErrorHandler != null) { 743 String msg = DOMMessageFormatter.formatMessage( 744 DOMMessageFormatter.XML_DOMAIN,"CantBindXMLNS",null ); 745 modifyDOMError(msg, DOMError.SEVERITY_ERROR, null, attr); 746 boolean continueProcess = fDOMErrorHandler.handleError(fDOMError); 747 if (!continueProcess) { 748 throw new RuntimeException ( 750 DOMMessageFormatter.formatMessage( 751 DOMMessageFormatter.SERIALIZER_DOMAIN, 752 "SerializationStopped", null)); 753 } 754 } 755 } else { 756 prefix = attr.getPrefix(); 757 prefix = (prefix == null || 758 prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix); 759 String localpart = fSymbolTable.addSymbol( attr.getLocalName()); 760 if (prefix == XMLSymbols.PREFIX_XMLNS) { value = fSymbolTable.addSymbol(value); 762 if (value.length() != 0) { 764 fNSBinder.declarePrefix(localpart, value); 765 } else { 766 } 769 continue; 770 } else { 773 value = fSymbolTable.addSymbol(value); 774 fNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, value); 775 continue; 776 } 777 } } } 781 uri = elem.getNamespaceURI(); 785 prefix = elem.getPrefix(); 786 787 if ((uri !=null && prefix !=null ) && uri.length() == 0 && prefix.length()!=0) { 793 prefix = null; 797 _printer.printText( '<' ); 798 _printer.printText( elem.getLocalName() ); 799 _printer.indent(); 800 } else { 801 _printer.printText( '<' ); 802 _printer.printText( tagName ); 803 _printer.indent(); 804 } 805 806 807 833 834 if (uri != null) { uri = fSymbolTable.addSymbol(uri); 836 prefix = (prefix == null || 837 prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix); 838 if (fNSBinder.getURI(prefix) == uri) { 839 845 } else { 846 if (fNamespacePrefixes) { 850 printNamespaceAttr(prefix, uri); 851 } 852 fLocalNSBinder.declarePrefix(prefix, uri); 853 fNSBinder.declarePrefix(prefix, uri); 854 } 855 } else { if (elem.getLocalName() == null) { 857 if (fDOMErrorHandler != null) { 859 String msg = DOMMessageFormatter.formatMessage( 860 DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName", 861 new Object []{elem.getNodeName()}); 862 modifyDOMError(msg,DOMError.SEVERITY_ERROR, null, elem); 863 boolean continueProcess = fDOMErrorHandler.handleError(fDOMError); 864 if (!continueProcess) { 866 throw new RuntimeException ( 867 DOMMessageFormatter.formatMessage( 868 DOMMessageFormatter.SERIALIZER_DOMAIN, 869 "SerializationStopped", null)); 870 } 871 } 872 } else { uri = fNSBinder.getURI(XMLSymbols.EMPTY_STRING); 874 875 if (uri !=null && uri.length() > 0) { 876 if (fNamespacePrefixes) { 879 printNamespaceAttr(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); 880 } 881 fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); 882 fNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); 883 } 884 } 885 } 886 887 888 893 for (i = 0; i < length; i++) { 894 895 attr = (Attr ) attrMap.item( i ); 896 value = attr.getValue(); 897 name = attr.getNodeName(); 898 899 uri = attr.getNamespaceURI(); 900 901 if (uri !=null && uri.length() == 0) { 903 uri=null; 904 name=attr.getLocalName(); 906 } 907 908 if (DEBUG) { 909 System.out.println("==>process attribute: "+attr.getNodeName()); 910 } 911 if (value == null) { 913 value=XMLSymbols.EMPTY_STRING; 914 } 915 916 if (uri != null) { prefix = attr.getPrefix(); 918 prefix = prefix == null ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix); 919 String localpart = fSymbolTable.addSymbol( attr.getLocalName()); 920 921 922 923 if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) { 927 prefix = attr.getPrefix(); 929 prefix = (prefix == null || 930 prefix.length() == 0) ? XMLSymbols.EMPTY_STRING : fSymbolTable.addSymbol(prefix); 931 localpart = fSymbolTable.addSymbol( attr.getLocalName()); 932 if (prefix == XMLSymbols.PREFIX_XMLNS) { localUri = fLocalNSBinder.getURI(localpart); value = fSymbolTable.addSymbol(value); 935 if (value.length() != 0 ) { 936 if (localUri == null) { 937 939 if (fNamespacePrefixes) { 942 printNamespaceAttr(localpart, value); 943 } 944 945 fLocalNSBinder.declarePrefix(localpart, value); 952 } 953 } else { 954 } 957 continue; 958 } else { 961 uri = fNSBinder.getURI(XMLSymbols.EMPTY_STRING); 962 localUri=fLocalNSBinder.getURI(XMLSymbols.EMPTY_STRING); 963 value = fSymbolTable.addSymbol(value); 964 if (localUri == null ){ 965 if (fNamespacePrefixes) { 967 printNamespaceAttr(XMLSymbols.EMPTY_STRING, value); 968 } 969 } 972 continue; 973 } 974 975 } 976 uri = fSymbolTable.addSymbol(uri); 977 978 String declaredURI = fNSBinder.getURI(prefix); 980 981 if (prefix == XMLSymbols.EMPTY_STRING || declaredURI != uri) { 982 988 name = attr.getNodeName(); 989 String declaredPrefix = fNSBinder.getPrefix(uri); 992 993 if (declaredPrefix !=null && declaredPrefix !=XMLSymbols.EMPTY_STRING) { 994 prefix = declaredPrefix; 996 name=prefix+":"+localpart; 997 } else { 998 if (DEBUG) { 999 System.out.println("==> cound not find prefix for the attribute: " +prefix); 1000 } 1001 1002 if (prefix != XMLSymbols.EMPTY_STRING && fLocalNSBinder.getURI(prefix) == null) { 1003 1005 } else { 1007 int counter = 1; 1010 prefix = fSymbolTable.addSymbol(PREFIX + counter++); 1011 while (fLocalNSBinder.getURI(prefix)!=null) { 1012 prefix = fSymbolTable.addSymbol(PREFIX +counter++); 1013 } 1014 name=prefix+":"+localpart; 1015 } 1016 if (fNamespacePrefixes) { 1018 printNamespaceAttr(prefix, uri); 1019 } 1020 value = fSymbolTable.addSymbol(value); 1021 fLocalNSBinder.declarePrefix(prefix, value); 1022 fNSBinder.declarePrefix(prefix, uri); 1023 } 1024 1025 } 1027 1028 printAttribute (name, (value==null)?XMLSymbols.EMPTY_STRING:value, attr.getSpecified(), attr); 1029 } else { if (attr.getLocalName() == null) { 1031 if (fDOMErrorHandler != null) { 1032 String msg = DOMMessageFormatter.formatMessage( 1033 DOMMessageFormatter.DOM_DOMAIN, 1034 "NullLocalAttrName", new Object []{attr.getNodeName()}); 1035 modifyDOMError(msg, DOMError.SEVERITY_ERROR, null, attr); 1036 boolean continueProcess = fDOMErrorHandler.handleError(fDOMError); 1037 if (!continueProcess) { 1038 throw new RuntimeException ( 1040 DOMMessageFormatter.formatMessage( 1041 DOMMessageFormatter.SERIALIZER_DOMAIN, 1042 "SerializationStopped", null)); 1043 } 1044 } 1045 printAttribute (name, value, attr.getSpecified(), attr); 1046 } else { 1048 printAttribute (name, value, attr.getSpecified(), attr); 1051 } 1052 } 1053 } 1055 } 1057 1058 if (elem.hasChildNodes()) { 1061 state = enterElementState( null, null, tagName, fPreserveSpace ); 1064 state.doCData = _format.isCDataElement( tagName ); 1065 state.unescaped = _format.isNonEscapingElement( tagName ); 1066 child = elem.getFirstChild(); 1067 while (child != null) { 1068 serializeNode( child ); 1069 child = child.getNextSibling(); 1070 } 1071 if (fNamespaces) { 1072 fNSBinder.popContext(); 1073 } 1074 endElementIO( null, null, tagName ); 1075 } else { 1076 if (DEBUG) { 1077 System.out.println("==>endElement: " +elem.getNodeName()); 1078 } 1079 if (fNamespaces) { 1080 fNSBinder.popContext(); 1081 } 1082 _printer.unindent(); 1083 _printer.printText( "/>" ); 1084 state.afterElement = true; 1086 state.afterComment = false; 1087 state.empty = false; 1088 if (isDocumentState()) 1089 _printer.flush(); 1090 } 1091 } 1092 1093 1094 1095 1103 1104 private void printNamespaceAttr(String prefix, String uri) throws IOException { 1105 _printer.printSpace(); 1106 if (prefix == XMLSymbols.EMPTY_STRING) { 1107 if (DEBUG) { 1108 System.out.println("=>add xmlns=\""+uri+"\" declaration"); 1109 } 1110 _printer.printText( XMLSymbols.PREFIX_XMLNS ); 1111 } else { 1112 if (DEBUG) { 1113 System.out.println("=>add xmlns:"+prefix+"=\""+uri+"\" declaration"); 1114 } 1115 _printer.printText( "xmlns:"+prefix ); 1116 } 1117 _printer.printText( "=\"" ); 1118 printEscaped( uri ); 1119 _printer.printText( '"' ); 1120 } 1121 1122 1123 1124 1133 private void printAttribute (String name, String value, boolean isSpecified, Attr attr) throws IOException { 1134 1135 if (isSpecified || (features & DOMSerializerImpl.DISCARDDEFAULT) == 0) { 1136 if (fDOMFilter !=null && 1137 (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ATTRIBUTE)!= 0) { 1138 short code = fDOMFilter.acceptNode(attr); 1139 switch (code) { 1140 case NodeFilter.FILTER_REJECT: 1141 case NodeFilter.FILTER_SKIP: { 1142 return; 1143 } 1144 default: { 1145 } 1147 } 1148 } 1149 _printer.printSpace(); 1150 _printer.printText( name ); 1151 _printer.printText( "=\"" ); 1152 printEscaped( value ); 1153 _printer.printText( '"' ); 1154 } 1155 1156 if (name.equals( "xml:space" )) { 1160 if (value.equals( "preserve" )) 1161 fPreserveSpace = true; 1162 else 1163 fPreserveSpace = _format.getPreserveSpace(); 1164 } 1165 } 1166 1167 protected String getEntityRef( int ch ) { 1168 switch (ch) { 1171 case '<': 1172 return "lt"; 1173 case '>': 1174 return "gt"; 1175 case '"': 1176 return "quot"; 1177 case '\'': 1178 return "apos"; 1179 case '&': 1180 return "amp"; 1181 } 1182 return null; 1183 } 1184 1185 1186 1189 private Attributes extractNamespaces( Attributes attrs ) 1190 throws SAXException 1191 { 1192 AttributesImpl attrsOnly; 1193 String rawName; 1194 int i; 1195 int indexColon; 1196 String prefix; 1197 int length; 1198 1199 if (attrs == null) { 1200 return null; 1201 } 1202 length = attrs.getLength(); 1203 attrsOnly = new AttributesImpl ( attrs ); 1204 1205 for (i = length - 1 ; i >= 0 ; --i) { 1206 rawName = attrsOnly.getQName( i ); 1207 1208 if (rawName.startsWith( "xmlns" )) { 1212 if (rawName.length() == 5) { 1213 startPrefixMapping( "", attrs.getValue( i ) ); 1214 attrsOnly.removeAttribute( i ); 1215 } else if (rawName.charAt(5) == ':') { 1216 startPrefixMapping(rawName.substring(6), attrs.getValue(i)); 1217 attrsOnly.removeAttribute( i ); 1218 } 1219 } 1220 } 1221 return attrsOnly; 1222 } 1223 1224 protected void printEscaped(String source) throws IOException { 1228 int length = source.length(); 1229 for (int i = 0; i < length; ++i) { 1230 int ch = source.charAt(i); 1231 if (!XMLChar.isValid(ch)) { 1232 if (++i < length) { 1233 surrogates(ch, source.charAt(i)); 1234 } else { 1235 fatalError("The character '" + (char) ch + "' is an invalid XML character"); 1236 } 1237 continue; 1238 } 1239 if (ch == '\n' || ch == '\r' || ch == '\t') { 1241 printHex(ch); 1242 } else if (ch == '<') { 1243 _printer.printText("<"); 1244 } else if (ch == '&') { 1245 _printer.printText("&"); 1246 } else if (ch == '"') { 1247 _printer.printText("""); 1248 } else if ((ch >= ' ' && _encodingInfo.isPrintable((char) ch))) { 1249 _printer.printText((char) ch); 1250 } else { 1251 printHex(ch); 1252 } 1253 } 1254 } 1255 1256 1257 protected void printXMLChar( int ch) throws IOException { 1258 if (ch == '\r') { 1259 printHex(ch); 1260 } else if ( ch == '<') { 1261 _printer.printText("<"); 1262 } else if (ch == '&') { 1263 _printer.printText("&"); 1264 } else if (ch == '>'){ 1265 _printer.printText(">"); 1268 } else if ( ch == '\n' || ch == '\t' || 1269 ( ch >= ' ' && _encodingInfo.isPrintable((char)ch))) { 1270 _printer.printText((char)ch); 1271 } else { 1272 printHex(ch); 1273 } 1274 } 1275 1276 protected void printText( String text, boolean preserveSpace, boolean unescaped ) 1277 throws IOException { 1278 int index; 1279 char ch; 1280 int length = text.length(); 1281 if ( preserveSpace ) { 1282 for ( index = 0 ; index < length ; ++index ) { 1287 ch = text.charAt( index ); 1288 if (!XMLChar.isValid(ch)) { 1289 if (++index <length) { 1291 surrogates(ch, text.charAt(index)); 1292 } else { 1293 fatalError("The character '"+(char)ch+"' is an invalid XML character"); 1294 } 1295 continue; 1296 } 1297 if ( unescaped ) { 1298 _printer.printText( ch ); 1299 } else 1300 printXMLChar( ch ); 1301 } 1302 } else { 1303 for ( index = 0 ; index < length ; ++index ) { 1309 ch = text.charAt( index ); 1310 if (!XMLChar.isValid(ch)) { 1311 if (++index <length) { 1313 surrogates(ch, text.charAt(index)); 1314 } else { 1315 fatalError("The character '"+(char)ch+"' is an invalid XML character"); 1316 } 1317 continue; 1318 } 1319 1320 if ( unescaped ) 1321 _printer.printText( ch ); 1322 else 1323 printXMLChar( ch); 1324 } 1325 } 1326 } 1327 1328 1329 1330 protected void printText( char[] chars, int start, int length, 1331 boolean preserveSpace, boolean unescaped ) throws IOException { 1332 int index; 1333 char ch; 1334 1335 if ( preserveSpace ) { 1336 while ( length-- > 0 ) { 1341 ch = chars[start++]; 1342 if (!XMLChar.isValid(ch)) { 1343 if ( length-- > 0 ) { 1345 surrogates(ch, chars[start++]); 1346 } else { 1347 fatalError("The character '"+(char)ch+"' is an invalid XML character"); 1348 } 1349 continue; 1350 } 1351 if ( unescaped ) 1352 _printer.printText( ch ); 1353 else 1354 printXMLChar( ch ); 1355 } 1356 } else { 1357 while ( length-- > 0 ) { 1363 ch = chars[start++]; 1364 if (!XMLChar.isValid(ch)) { 1365 if ( length-- > 0 ) { 1367 surrogates(ch, chars[start++]); 1368 } else { 1369 fatalError("The character '"+(char)ch+"' is an invalid XML character"); 1370 } 1371 continue; 1372 } 1373 if ( unescaped ) 1374 _printer.printText( ch ); 1375 else 1376 printXMLChar( ch ); 1377 } 1378 } 1379 } 1380 1381 1382 1388 protected void checkUnboundNamespacePrefixedNode (Node node) throws IOException { 1389 1390 if (fNamespaces) { 1391 1392 if (DEBUG) { 1393 System.out.println("==>serializeNode("+node.getNodeName()+") [Entity Reference - Namespaces on]"); 1394 System.out.println("==>Declared Prefix Count: " + fNSBinder.getDeclaredPrefixCount()); 1395 System.out.println("==>Node Name: " + node.getNodeName()); 1396 System.out.println("==>First Child Node Name: " + node.getFirstChild().getNodeName()); 1397 System.out.println("==>First Child Node Prefix: " + node.getFirstChild().getPrefix()); 1398 System.out.println("==>First Child Node NamespaceURI: " + node.getFirstChild().getNamespaceURI()); 1399 } 1400 1401 1402 Node child, next; 1403 for (child = node.getFirstChild(); child != null; child = next) { 1404 next = child.getNextSibling(); 1405 if (DEBUG) { 1406 System.out.println("==>serializeNode("+child.getNodeName()+") [Child Node]"); 1407 System.out.println("==>serializeNode("+child.getPrefix()+") [Child Node Prefix]"); 1408 } 1409 1410 String prefix = child.getPrefix(); 1413 prefix = (prefix == null || 1414 prefix.length() == 0) ? XMLSymbols.EMPTY_STRING : fSymbolTable.addSymbol(prefix); 1415 if (fNSBinder.getURI(prefix) == null && prefix != null) { 1416 fatalError("The replacement text of the entity node '" 1417 + node.getNodeName() 1418 + "' contains an element node '" 1419 + child.getNodeName() 1420 + "' with an undeclared prefix '" 1421 + prefix + "'."); 1422 } 1423 1424 if (child.getNodeType() == Node.ELEMENT_NODE) { 1425 1426 NamedNodeMap attrs = child.getAttributes(); 1427 1428 for (int i = 0; i< attrs.getLength(); i++ ) { 1429 1430 String attrPrefix = attrs.item(i).getPrefix(); 1431 attrPrefix = (attrPrefix == null || 1432 attrPrefix.length() == 0) ? XMLSymbols.EMPTY_STRING : fSymbolTable.addSymbol(attrPrefix); 1433 if (fNSBinder.getURI(attrPrefix) == null && attrPrefix != null) { 1434 fatalError("The replacement text of the entity node '" 1435 + node.getNodeName() 1436 + "' contains an element node '" 1437 + child.getNodeName() 1438 + "' with an attribute '" 1439 + attrs.item(i).getNodeName() 1440 + "' an undeclared prefix '" 1441 + attrPrefix + "'."); 1442 } 1443 1444 } 1445 1446 } 1447 1448 if (child.hasChildNodes()) { 1449 checkUnboundNamespacePrefixedNode(child); 1450 } 1451 } 1452 } 1453 } 1454 1455 public boolean reset() { 1456 super.reset(); 1457 if (fNSBinder != null){ 1458 fNSBinder.reset(); 1459 fNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); 1462 } 1463 return true; 1464 } 1465 1466} 1467 1468 1469 1470 1471 | Popular Tags |