1 57 58 59 60 73 74 package org.enhydra.apache.xml.serialize; 75 76 77 import java.io.IOException ; 78 import java.io.OutputStream ; 79 import java.io.Writer ; 80 import java.util.Enumeration ; 81 82 import org.w3c.dom.Attr ; 83 import org.w3c.dom.Element ; 84 import org.w3c.dom.NamedNodeMap ; 85 import org.w3c.dom.Node ; 86 import org.xml.sax.AttributeList ; 87 import org.xml.sax.Attributes ; 88 import org.xml.sax.SAXException ; 89 import org.xml.sax.helpers.AttributesImpl ; 90 91 92 121 public class XMLSerializer 122 extends BaseMarkupSerializer 123 { 124 125 126 131 public XMLSerializer() 132 { 133 super( new OutputFormat( Method.XML, null, false ) ); 134 } 135 136 137 142 public XMLSerializer( OutputFormat format ) 143 { 144 super( format != null ? format : new OutputFormat( Method.XML, null, false ) ); 145 _format.setMethod( Method.XML ); 146 } 147 148 149 157 public XMLSerializer( Writer writer, OutputFormat format ) 158 { 159 super( format != null ? format : new OutputFormat( Method.XML, null, false ) ); 160 _format.setMethod( Method.XML ); 161 setOutputCharStream( writer ); 162 } 163 164 165 173 public XMLSerializer( OutputStream output, OutputFormat format ) 174 { 175 super( format != null ? format : new OutputFormat( Method.XML, null, false ) ); 176 _format.setMethod( Method.XML ); 177 setOutputByteStream( output ); 178 } 179 180 181 public void setOutputFormat( OutputFormat format ) 182 { 183 super.setOutputFormat( format != null ? format : new OutputFormat( Method.XML, null, false ) ); 184 } 185 186 187 191 192 public void startElement( String namespaceURI, String localName, 193 String rawName, Attributes attrs ) 194 throws SAXException 195 { 196 int i; 197 boolean preserveSpace; 198 ElementState state; 199 String name; 200 String value; 201 boolean addNSAttr = false; 202 203 try { 204 if ( _printer == null ) 205 throw new IllegalStateException ( "SER002 No writer supplied for serializer" ); 206 207 state = getElementState(); 208 if ( isDocumentState() ) { 209 if ( ! _started ) 214 startDocument( ( localName == null || localName.length() == 0 ) ? rawName : localName ); 215 } else { 216 if ( state.empty ) 220 _printer.printText( '>' ); 221 if ( state.inCData ) 223 { 224 _printer.printText( "]]>" ); 225 state.inCData = false; 226 } 227 if ( _indenting && ! state.preserveSpace && 231 ( state.empty || state.afterElement || state.afterComment) ) 232 _printer.breakLine(); 233 } 234 preserveSpace = state.preserveSpace; 235 236 attrs = extractNamespaces(attrs); 239 240 if ( rawName == null || rawName.length() == 0 ) { 243 if ( localName == null ) 244 throw new SAXException ( "No rawName and localName is null" ); 245 if ( namespaceURI != null && ! namespaceURI.equals( "" ) ) { 246 String prefix; 247 prefix = getPrefix( namespaceURI ); 248 if ( prefix != null && prefix.length() > 0 ) 249 rawName = prefix + ":" + localName; 250 else 251 rawName = localName; 252 } else 253 rawName = localName; 254 addNSAttr = true; 255 } 256 257 _printer.printText( '<' ); 258 _printer.printText( rawName ); 259 _printer.indent(); 260 261 if ( attrs != null ) { 265 for ( i = 0 ; i < attrs.getLength() ; ++i ) { 266 _printer.printSpace(); 267 268 name = attrs.getQName( i ); 269 if ( name != null && name.length() == 0 ) { 270 String prefix; 271 String attrURI; 272 273 name = attrs.getLocalName( i ); 274 attrURI = attrs.getURI( i ); 275 if ( ( attrURI != null && attrURI.length() != 0 ) && 276 ( namespaceURI == null || namespaceURI.length() == 0 || 277 ! attrURI.equals( namespaceURI ) ) ) { 278 prefix = getPrefix( attrURI ); 279 if ( prefix != null && prefix.length() > 0 ) 280 name = prefix + ":" + name; 281 } 282 } 283 284 value = attrs.getValue( i ); 285 if ( value == null ) 286 value = ""; 287 _printer.printText( name ); 288 _printer.printText( "=\"" ); 289 printEscaped( value ); 290 _printer.printText( '"' ); 291 292 if ( name.equals( "xml:space" ) ) { 296 if ( value.equals( "preserve" ) ) 297 preserveSpace = true; 298 else 299 preserveSpace = _format.getPreserveSpace(); 300 } 301 } 302 } 303 304 if ( _prefixes != null ) { 305 Enumeration enumer; 306 307 enumer = _prefixes.keys(); 308 while ( enumer.hasMoreElements() ) { 309 _printer.printSpace(); 310 value = (String ) enumer.nextElement(); 311 name = (String ) _prefixes.get( value ); 312 if ( name.length() == 0 ) { 313 _printer.printText( "xmlns=\"" ); 314 printEscaped( value ); 315 _printer.printText( '"' ); 316 } else { 317 _printer.printText( "xmlns:" ); 318 _printer.printText( name ); 319 _printer.printText( "=\"" ); 320 printEscaped( value ); 321 _printer.printText( '"' ); 322 } 323 } 324 } 325 326 state = enterElementState( namespaceURI, localName, rawName, preserveSpace ); 330 name = ( localName == null || localName.length() == 0 ) ? rawName : namespaceURI + "^" + localName; 331 state.doCData = _format.isCDataElement( name ); 332 state.unescaped = _format.isNonEscapingElement( name ); 333 } catch ( IOException except ) { 334 throw new SAXException ( except ); 335 } 336 } 337 338 339 public void endElement( String namespaceURI, String localName, 340 String rawName ) 341 throws SAXException 342 { 343 try { 344 endElementIO( namespaceURI, localName, rawName ); 345 } catch ( IOException except ) { 346 throw new SAXException ( except ); 347 } 348 } 349 350 351 public void endElementIO( String namespaceURI, String localName, 352 String rawName ) 353 throws IOException 354 { 355 ElementState state; 356 357 _printer.unindent(); 361 state = getElementState(); 362 if ( state.empty ) { 363 _printer.printText( "/>" ); 364 } else { 365 if ( state.inCData ) 367 _printer.printText( "]]>" ); 368 if ( _indenting && ! state.preserveSpace && (state.afterElement || state.afterComment) ) 372 _printer.breakLine(); 373 _printer.printText( "</" ); 374 _printer.printText( state.rawName ); 375 _printer.printText( '>' ); 376 } 377 state = leaveElementState(); 380 state.afterElement = true; 381 state.afterComment = false; 382 state.empty = false; 383 if ( isDocumentState() ) 384 _printer.flush(); 385 } 386 387 388 392 393 public void startElement( String tagName, AttributeList attrs ) 394 throws SAXException 395 { 396 int i; 397 boolean preserveSpace; 398 ElementState state; 399 String name; 400 String value; 401 402 try { 403 if ( _printer == null ) 404 throw new IllegalStateException ( "SER002 No writer supplied for serializer" ); 405 406 state = getElementState(); 407 if ( isDocumentState() ) { 408 if ( ! _started ) 413 startDocument( tagName ); 414 } else { 415 if ( state.empty ) 419 _printer.printText( '>' ); 420 if ( state.inCData ) 422 { 423 _printer.printText( "]]>" ); 424 state.inCData = false; 425 } 426 if ( _indenting && ! state.preserveSpace && 430 ( state.empty || state.afterElement || state.afterComment) ) 431 _printer.breakLine(); 432 } 433 preserveSpace = state.preserveSpace; 434 435 438 _printer.printText( '<' ); 439 _printer.printText( tagName ); 440 _printer.indent(); 441 442 if ( attrs != null ) { 446 for ( i = 0 ; i < attrs.getLength() ; ++i ) { 447 _printer.printSpace(); 448 name = attrs.getName( i ); 449 value = attrs.getValue( i ); 450 if ( value != null ) { 451 _printer.printText( name ); 452 _printer.printText( "=\"" ); 453 printEscaped( value ); 454 _printer.printText( '"' ); 455 } 456 457 if ( name.equals( "xml:space" ) ) { 461 if ( value.equals( "preserve" ) ) 462 preserveSpace = true; 463 else 464 preserveSpace = _format.getPreserveSpace(); 465 } 466 } 467 } 468 state = enterElementState( null, null, tagName, preserveSpace ); 472 state.doCData = _format.isCDataElement( tagName ); 473 state.unescaped = _format.isNonEscapingElement( tagName ); 474 } catch ( IOException except ) { 475 throw new SAXException ( except ); 476 } 477 478 } 479 480 481 public void endElement( String tagName ) 482 throws SAXException 483 { 484 endElement( null, null, tagName ); 485 } 486 487 488 489 493 494 506 protected void startDocument( String rootTagName ) 507 throws IOException 508 { 509 int i; 510 String dtd; 511 512 dtd = _printer.leaveDTD(); 513 if ( ! _started ) { 514 515 if ( ! _format.getOmitXMLDeclaration() ) { 516 StringBuffer buffer; 517 518 buffer = new StringBuffer ( "<?xml version=\"" ); 521 if ( _format.getVersion() != null ) 522 buffer.append( _format.getVersion() ); 523 else 524 buffer.append( "1.0" ); 525 buffer.append( '"' ); 526 if ( _format.getEncoding() != null ) { 527 buffer.append( " encoding=\"" ); 528 buffer.append( _format.getEncoding() ); 529 buffer.append( '"' ); 530 } 531 if ( _format.getStandalone() && _docTypeSystemId == null && 532 _docTypePublicId == null ) 533 buffer.append( " standalone=\"yes\"" ); 534 buffer.append( "?>" ); 535 _printer.printText( buffer ); 536 _printer.breakLine(); 537 } 538 539 if ( ! _format.getOmitDocumentType() ) { 540 if ( _docTypeSystemId != null ) { 541 _printer.printText( "<!DOCTYPE " ); 545 _printer.printText( rootTagName ); 546 if ( _docTypePublicId != null ) { 547 _printer.printText( " PUBLIC " ); 548 printDoctypeURL( _docTypePublicId ); 549 if ( _indenting ) { 550 _printer.breakLine(); 551 for ( i = 0 ; i < 18 + rootTagName.length() ; ++i ) 552 _printer.printText( " " ); 553 } else 554 _printer.printText( " " ); 555 printDoctypeURL( _docTypeSystemId ); 556 } 557 else { 558 _printer.printText( " SYSTEM " ); 559 printDoctypeURL( _docTypeSystemId ); 560 } 561 562 if ( dtd != null && dtd.length() > 0 ) { 565 _printer.printText( " [" ); 566 printText( dtd, true, true ); 567 _printer.printText( ']' ); 568 } 569 570 _printer.printText( ">" ); 571 _printer.breakLine(); 572 } else if ( dtd != null && dtd.length() > 0 ) { 573 _printer.printText( "<!DOCTYPE " ); 574 _printer.printText( rootTagName ); 575 _printer.printText( " [" ); 576 printText( dtd, true, true ); 577 _printer.printText( "]>" ); 578 _printer.breakLine(); 579 } 580 } 581 } 582 _started = true; 583 serializePreRoot(); 585 } 586 587 588 593 protected void serializeElement( Element elem ) 594 throws IOException 595 { 596 Attr attr; 597 NamedNodeMap attrMap; 598 int i; 599 Node child; 600 ElementState state; 601 boolean preserveSpace; 602 String name; 603 String value; 604 String tagName; 605 606 tagName = elem.getTagName(); 607 state = getElementState(); 608 if ( isDocumentState() ) { 609 if ( ! _started ) 614 startDocument( tagName ); 615 } else { 616 if ( state.empty ) 620 _printer.printText( '>' ); 621 if ( state.inCData ) 623 { 624 _printer.printText( "]]>" ); 625 state.inCData = false; 626 } 627 if ( _indenting && ! state.preserveSpace && 631 ( state.empty || state.afterElement || state.afterComment) ) 632 _printer.breakLine(); 633 } 634 preserveSpace = state.preserveSpace; 635 636 639 _printer.printText( '<' ); 640 _printer.printText( tagName ); 641 _printer.indent(); 642 643 attrMap = elem.getAttributes(); 649 if ( attrMap != null ) { 650 for ( i = 0 ; i < attrMap.getLength() ; ++i ) { 651 attr = (Attr ) attrMap.item( i ); 652 name = attr.getName(); 653 value = attr.getValue(); 654 if ( value == null ) 655 value = ""; 656 if ( attr.getSpecified() ) { 657 _printer.printSpace(); 658 _printer.printText( name ); 659 _printer.printText( "=\"" ); 660 printEscaped( value ); 661 _printer.printText( '"' ); 662 } 663 if ( name.equals( "xml:space" ) ) { 667 if ( value.equals( "preserve" ) ) 668 preserveSpace = true; 669 else 670 preserveSpace = _format.getPreserveSpace(); 671 } 672 } 673 } 674 675 if ( elem.hasChildNodes() ) { 678 state = enterElementState( null, null, tagName, preserveSpace ); 681 state.doCData = _format.isCDataElement( tagName ); 682 state.unescaped = _format.isNonEscapingElement( tagName ); 683 child = elem.getFirstChild(); 684 while ( child != null ) { 685 serializeNode( child ); 686 child = child.getNextSibling(); 687 } 688 endElementIO( null, null, tagName ); 689 } else { 690 _printer.unindent(); 691 _printer.printText( "/>" ); 692 state.afterElement = true; 694 state.afterComment = false; 695 state.empty = false; 696 if ( isDocumentState() ) 697 _printer.flush(); 698 } 699 } 700 701 702 protected String getEntityRef( int ch ) 703 { 704 switch ( ch ) { 707 case '<': 708 return "lt"; 709 case '>': 710 return "gt"; 711 case '"': 712 return "quot"; 713 case '\'': 714 return "apos"; 715 case '&': 716 return "amp"; 717 } 718 return null; 719 } 720 721 722 725 private Attributes extractNamespaces( Attributes attrs ) 726 throws SAXException 727 { 728 AttributesImpl attrsOnly; 729 String rawName; 730 int i; 731 int indexColon; 732 String prefix; 733 int length; 734 735 length = attrs.getLength(); 736 attrsOnly = new AttributesImpl ( attrs ); 737 738 for ( i = length - 1 ; i >= 0 ; --i ) { 739 rawName = attrsOnly.getQName( i ); 740 741 if ( rawName.startsWith( "xmlns" ) ) { 745 if (rawName.length() == 5) { 746 startPrefixMapping( "", attrs.getValue( i ) ); 747 attrsOnly.removeAttribute( i ); 748 } else if (rawName.charAt(5) == ':') { 749 startPrefixMapping(rawName.substring(6), attrs.getValue(i)); 750 attrsOnly.removeAttribute( i ); 751 } 752 } 753 } 754 return attrsOnly; 755 } 756 } 757 758 759 | Popular Tags |