1 16 19 package org.apache.xml.serializer; 20 21 import java.io.IOException ; 22 import java.io.OutputStream ; 23 import java.io.UnsupportedEncodingException ; 24 import java.util.Properties ; 25 26 import javax.xml.transform.Result ; 27 28 import org.apache.xml.res.XMLErrorResources; 29 import org.apache.xml.res.XMLMessages; 30 import org.apache.xml.utils.BoolStack; 31 import org.apache.xml.utils.Trie; 32 import org.xml.sax.Attributes ; 33 import org.xml.sax.SAXException ; 34 35 39 public class ToHTMLStream extends ToStream 40 { 41 42 43 protected boolean m_inDTD = false; 44 45 47 private boolean m_inBlockElem = false; 48 49 53 protected static final CharInfo m_htmlcharInfo = 54 CharInfo.getCharInfo(CharInfo.HTML_ENTITIES_RESOURCE, Method.HTML); 56 57 58 static final Trie m_elementFlags = new Trie(); 59 60 static { 61 62 m_elementFlags.put("BASEFONT", new ElemDesc(0 | ElemDesc.EMPTY)); 64 m_elementFlags.put( 65 "FRAME", 66 new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK)); 67 m_elementFlags.put("FRAMESET", new ElemDesc(0 | ElemDesc.BLOCK)); 68 m_elementFlags.put("NOFRAMES", new ElemDesc(0 | ElemDesc.BLOCK)); 69 m_elementFlags.put( 70 "ISINDEX", 71 new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK)); 72 m_elementFlags.put( 73 "APPLET", 74 new ElemDesc(0 | ElemDesc.WHITESPACESENSITIVE)); 75 m_elementFlags.put("CENTER", new ElemDesc(0 | ElemDesc.BLOCK)); 76 m_elementFlags.put("DIR", new ElemDesc(0 | ElemDesc.BLOCK)); 77 m_elementFlags.put("MENU", new ElemDesc(0 | ElemDesc.BLOCK)); 78 79 m_elementFlags.put("TT", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 81 m_elementFlags.put("I", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 82 m_elementFlags.put("B", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 83 m_elementFlags.put("BIG", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 84 m_elementFlags.put("SMALL", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 85 m_elementFlags.put("EM", new ElemDesc(0 | ElemDesc.PHRASE)); 86 m_elementFlags.put("STRONG", new ElemDesc(0 | ElemDesc.PHRASE)); 87 m_elementFlags.put("DFN", new ElemDesc(0 | ElemDesc.PHRASE)); 88 m_elementFlags.put("CODE", new ElemDesc(0 | ElemDesc.PHRASE)); 89 m_elementFlags.put("SAMP", new ElemDesc(0 | ElemDesc.PHRASE)); 90 m_elementFlags.put("KBD", new ElemDesc(0 | ElemDesc.PHRASE)); 91 m_elementFlags.put("VAR", new ElemDesc(0 | ElemDesc.PHRASE)); 92 m_elementFlags.put("CITE", new ElemDesc(0 | ElemDesc.PHRASE)); 93 m_elementFlags.put("ABBR", new ElemDesc(0 | ElemDesc.PHRASE)); 94 m_elementFlags.put("ACRONYM", new ElemDesc(0 | ElemDesc.PHRASE)); 95 m_elementFlags.put( 96 "SUP", 97 new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL)); 98 m_elementFlags.put( 99 "SUB", 100 new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL)); 101 m_elementFlags.put( 102 "SPAN", 103 new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL)); 104 m_elementFlags.put( 105 "BDO", 106 new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL)); 107 m_elementFlags.put( 108 "BR", 109 new ElemDesc( 110 0 111 | ElemDesc.SPECIAL 112 | ElemDesc.ASPECIAL 113 | ElemDesc.EMPTY 114 | ElemDesc.BLOCK)); 115 m_elementFlags.put("BODY", new ElemDesc(0 | ElemDesc.BLOCK)); 116 m_elementFlags.put( 117 "ADDRESS", 118 new ElemDesc( 119 0 120 | ElemDesc.BLOCK 121 | ElemDesc.BLOCKFORM 122 | ElemDesc.BLOCKFORMFIELDSET)); 123 m_elementFlags.put( 124 "DIV", 125 new ElemDesc( 126 0 127 | ElemDesc.BLOCK 128 | ElemDesc.BLOCKFORM 129 | ElemDesc.BLOCKFORMFIELDSET)); 130 m_elementFlags.put("A", new ElemDesc(0 | ElemDesc.SPECIAL)); 131 m_elementFlags.put( 132 "MAP", 133 new ElemDesc( 134 0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL | ElemDesc.BLOCK)); 135 m_elementFlags.put( 136 "AREA", 137 new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK)); 138 m_elementFlags.put( 139 "LINK", 140 new ElemDesc( 141 0 | ElemDesc.HEADMISC | ElemDesc.EMPTY | ElemDesc.BLOCK)); 142 m_elementFlags.put( 143 "IMG", 144 new ElemDesc( 145 0 146 | ElemDesc.SPECIAL 147 | ElemDesc.ASPECIAL 148 | ElemDesc.EMPTY 149 | ElemDesc.WHITESPACESENSITIVE)); 150 m_elementFlags.put( 151 "OBJECT", 152 new ElemDesc( 153 0 154 | ElemDesc.SPECIAL 155 | ElemDesc.ASPECIAL 156 | ElemDesc.HEADMISC 157 | ElemDesc.WHITESPACESENSITIVE)); 158 m_elementFlags.put("PARAM", new ElemDesc(0 | ElemDesc.EMPTY)); 159 m_elementFlags.put( 160 "HR", 161 new ElemDesc( 162 0 163 | ElemDesc.BLOCK 164 | ElemDesc.BLOCKFORM 165 | ElemDesc.BLOCKFORMFIELDSET 166 | ElemDesc.EMPTY)); 167 m_elementFlags.put( 168 "P", 169 new ElemDesc( 170 0 171 | ElemDesc.BLOCK 172 | ElemDesc.BLOCKFORM 173 | ElemDesc.BLOCKFORMFIELDSET)); 174 m_elementFlags.put( 175 "H1", 176 new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK)); 177 m_elementFlags.put( 178 "H2", 179 new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK)); 180 m_elementFlags.put( 181 "H3", 182 new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK)); 183 m_elementFlags.put( 184 "H4", 185 new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK)); 186 m_elementFlags.put( 187 "H5", 188 new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK)); 189 m_elementFlags.put( 190 "H6", 191 new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK)); 192 m_elementFlags.put( 193 "PRE", 194 new ElemDesc(0 | ElemDesc.PREFORMATTED | ElemDesc.BLOCK)); 195 m_elementFlags.put( 196 "Q", 197 new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL)); 198 m_elementFlags.put( 199 "BLOCKQUOTE", 200 new ElemDesc( 201 0 202 | ElemDesc.BLOCK 203 | ElemDesc.BLOCKFORM 204 | ElemDesc.BLOCKFORMFIELDSET)); 205 m_elementFlags.put("INS", new ElemDesc(0)); 206 m_elementFlags.put("DEL", new ElemDesc(0)); 207 m_elementFlags.put( 208 "DL", 209 new ElemDesc( 210 0 211 | ElemDesc.BLOCK 212 | ElemDesc.BLOCKFORM 213 | ElemDesc.BLOCKFORMFIELDSET)); 214 m_elementFlags.put("DT", new ElemDesc(0 | ElemDesc.BLOCK)); 215 m_elementFlags.put("DD", new ElemDesc(0 | ElemDesc.BLOCK)); 216 m_elementFlags.put( 217 "OL", 218 new ElemDesc(0 | ElemDesc.LIST | ElemDesc.BLOCK)); 219 m_elementFlags.put( 220 "UL", 221 new ElemDesc(0 | ElemDesc.LIST | ElemDesc.BLOCK)); 222 m_elementFlags.put("LI", new ElemDesc(0 | ElemDesc.BLOCK)); 223 m_elementFlags.put("FORM", new ElemDesc(0 | ElemDesc.BLOCK)); 224 m_elementFlags.put("LABEL", new ElemDesc(0 | ElemDesc.FORMCTRL)); 225 m_elementFlags.put( 226 "INPUT", 227 new ElemDesc( 228 0 | ElemDesc.FORMCTRL | ElemDesc.INLINELABEL | ElemDesc.EMPTY)); 229 m_elementFlags.put( 230 "SELECT", 231 new ElemDesc(0 | ElemDesc.FORMCTRL | ElemDesc.INLINELABEL)); 232 m_elementFlags.put("OPTGROUP", new ElemDesc(0)); 233 m_elementFlags.put("OPTION", new ElemDesc(0)); 234 m_elementFlags.put( 235 "TEXTAREA", 236 new ElemDesc(0 | ElemDesc.FORMCTRL | ElemDesc.INLINELABEL)); 237 m_elementFlags.put( 238 "FIELDSET", 239 new ElemDesc(0 | ElemDesc.BLOCK | ElemDesc.BLOCKFORM)); 240 m_elementFlags.put("LEGEND", new ElemDesc(0)); 241 m_elementFlags.put( 242 "BUTTON", 243 new ElemDesc(0 | ElemDesc.FORMCTRL | ElemDesc.INLINELABEL)); 244 m_elementFlags.put( 245 "TABLE", 246 new ElemDesc( 247 0 248 | ElemDesc.BLOCK 249 | ElemDesc.BLOCKFORM 250 | ElemDesc.BLOCKFORMFIELDSET)); 251 m_elementFlags.put("CAPTION", new ElemDesc(0 | ElemDesc.BLOCK)); 252 m_elementFlags.put("THEAD", new ElemDesc(0 | ElemDesc.BLOCK)); 253 m_elementFlags.put("TFOOT", new ElemDesc(0 | ElemDesc.BLOCK)); 254 m_elementFlags.put("TBODY", new ElemDesc(0 | ElemDesc.BLOCK)); 255 m_elementFlags.put("COLGROUP", new ElemDesc(0 | ElemDesc.BLOCK)); 256 m_elementFlags.put( 257 "COL", 258 new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK)); 259 m_elementFlags.put("TR", new ElemDesc(0 | ElemDesc.BLOCK)); 260 m_elementFlags.put("TH", new ElemDesc(0)); 261 m_elementFlags.put("TD", new ElemDesc(0)); 262 m_elementFlags.put( 263 "HEAD", 264 new ElemDesc(0 | ElemDesc.BLOCK | ElemDesc.HEADELEM)); 265 m_elementFlags.put("TITLE", new ElemDesc(0 | ElemDesc.BLOCK)); 266 m_elementFlags.put( 267 "BASE", 268 new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK)); 269 m_elementFlags.put( 270 "META", 271 new ElemDesc( 272 0 | ElemDesc.HEADMISC | ElemDesc.EMPTY | ElemDesc.BLOCK)); 273 m_elementFlags.put( 274 "STYLE", 275 new ElemDesc( 276 0 | ElemDesc.HEADMISC | ElemDesc.RAW | ElemDesc.BLOCK)); 277 m_elementFlags.put( 278 "SCRIPT", 279 new ElemDesc( 280 0 281 | ElemDesc.SPECIAL 282 | ElemDesc.ASPECIAL 283 | ElemDesc.HEADMISC 284 | ElemDesc.RAW)); 285 m_elementFlags.put( 286 "NOSCRIPT", 287 new ElemDesc( 288 0 289 | ElemDesc.BLOCK 290 | ElemDesc.BLOCKFORM 291 | ElemDesc.BLOCKFORMFIELDSET)); 292 m_elementFlags.put("HTML", new ElemDesc(0 | ElemDesc.BLOCK)); 293 294 m_elementFlags.put("FONT", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 298 299 m_elementFlags.put("S", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 301 m_elementFlags.put("STRIKE", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 302 303 m_elementFlags.put("U", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 305 306 m_elementFlags.put("NOBR", new ElemDesc(0 | ElemDesc.FONTSTYLE)); 308 309 m_elementFlags.put( 311 "IFRAME", 312 new ElemDesc( 313 0 314 | ElemDesc.BLOCK 315 | ElemDesc.BLOCKFORM 316 | ElemDesc.BLOCKFORMFIELDSET)); 317 m_elementFlags.put( 319 "LAYER", 320 new ElemDesc( 321 0 322 | ElemDesc.BLOCK 323 | ElemDesc.BLOCKFORM 324 | ElemDesc.BLOCKFORMFIELDSET)); 325 m_elementFlags.put( 326 "ILAYER", 327 new ElemDesc( 328 0 329 | ElemDesc.BLOCK 330 | ElemDesc.BLOCKFORM 331 | ElemDesc.BLOCKFORMFIELDSET)); 332 333 ElemDesc elemDesc; 334 335 elemDesc = (ElemDesc) m_elementFlags.get("AREA"); 336 337 elemDesc.setAttr("HREF", ElemDesc.ATTRURL); 338 elemDesc.setAttr("NOHREF", ElemDesc.ATTREMPTY); 339 340 elemDesc = (ElemDesc) m_elementFlags.get("BASE"); 341 342 elemDesc.setAttr("HREF", ElemDesc.ATTRURL); 343 344 elemDesc = (ElemDesc) m_elementFlags.get("BLOCKQUOTE"); 345 346 elemDesc.setAttr("CITE", ElemDesc.ATTRURL); 347 348 elemDesc = (ElemDesc) m_elementFlags.get("Q"); 349 350 elemDesc.setAttr("CITE", ElemDesc.ATTRURL); 351 352 elemDesc = (ElemDesc) m_elementFlags.get("INS"); 353 354 elemDesc.setAttr("CITE", ElemDesc.ATTRURL); 355 356 elemDesc = (ElemDesc) m_elementFlags.get("DEL"); 357 358 elemDesc.setAttr("CITE", ElemDesc.ATTRURL); 359 360 elemDesc = (ElemDesc) m_elementFlags.get("A"); 361 362 elemDesc.setAttr("HREF", ElemDesc.ATTRURL); 363 elemDesc.setAttr("NAME", ElemDesc.ATTRURL); 364 365 elemDesc = (ElemDesc) m_elementFlags.get("LINK"); 366 elemDesc.setAttr("HREF", ElemDesc.ATTRURL); 367 368 elemDesc = (ElemDesc) m_elementFlags.get("INPUT"); 369 370 elemDesc.setAttr("SRC", ElemDesc.ATTRURL); 371 elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL); 372 elemDesc.setAttr("CHECKED", ElemDesc.ATTREMPTY); 373 elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY); 374 elemDesc.setAttr("ISMAP", ElemDesc.ATTREMPTY); 375 elemDesc.setAttr("READONLY", ElemDesc.ATTREMPTY); 376 377 elemDesc = (ElemDesc) m_elementFlags.get("SELECT"); 378 379 elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY); 380 elemDesc.setAttr("MULTIPLE", ElemDesc.ATTREMPTY); 381 382 elemDesc = (ElemDesc) m_elementFlags.get("OPTGROUP"); 383 384 elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY); 385 386 elemDesc = (ElemDesc) m_elementFlags.get("OPTION"); 387 388 elemDesc.setAttr("SELECTED", ElemDesc.ATTREMPTY); 389 elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY); 390 391 elemDesc = (ElemDesc) m_elementFlags.get("TEXTAREA"); 392 393 elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY); 394 elemDesc.setAttr("READONLY", ElemDesc.ATTREMPTY); 395 396 elemDesc = (ElemDesc) m_elementFlags.get("BUTTON"); 397 398 elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY); 399 400 elemDesc = (ElemDesc) m_elementFlags.get("SCRIPT"); 401 402 elemDesc.setAttr("SRC", ElemDesc.ATTRURL); 403 elemDesc.setAttr("FOR", ElemDesc.ATTRURL); 404 elemDesc.setAttr("DEFER", ElemDesc.ATTREMPTY); 405 406 elemDesc = (ElemDesc) m_elementFlags.get("IMG"); 407 408 elemDesc.setAttr("SRC", ElemDesc.ATTRURL); 409 elemDesc.setAttr("LONGDESC", ElemDesc.ATTRURL); 410 elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL); 411 elemDesc.setAttr("ISMAP", ElemDesc.ATTREMPTY); 412 413 elemDesc = (ElemDesc) m_elementFlags.get("OBJECT"); 414 415 elemDesc.setAttr("CLASSID", ElemDesc.ATTRURL); 416 elemDesc.setAttr("CODEBASE", ElemDesc.ATTRURL); 417 elemDesc.setAttr("DATA", ElemDesc.ATTRURL); 418 elemDesc.setAttr("ARCHIVE", ElemDesc.ATTRURL); 419 elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL); 420 elemDesc.setAttr("DECLARE", ElemDesc.ATTREMPTY); 421 422 elemDesc = (ElemDesc) m_elementFlags.get("FORM"); 423 424 elemDesc.setAttr("ACTION", ElemDesc.ATTRURL); 425 426 elemDesc = (ElemDesc) m_elementFlags.get("HEAD"); 427 428 elemDesc.setAttr("PROFILE", ElemDesc.ATTRURL); 429 430 elemDesc = (ElemDesc) m_elementFlags.get("FRAME"); 432 433 elemDesc.setAttr("SRC", ElemDesc.ATTRURL); 434 elemDesc.setAttr("LONGDESC", ElemDesc.ATTRURL); 435 436 elemDesc = (ElemDesc) m_elementFlags.get("IFRAME"); 438 439 elemDesc.setAttr("SRC", ElemDesc.ATTRURL); 440 elemDesc.setAttr("LONGDESC", ElemDesc.ATTRURL); 441 442 elemDesc = (ElemDesc) m_elementFlags.get("LAYER"); 444 445 elemDesc.setAttr("SRC", ElemDesc.ATTRURL); 446 447 elemDesc = (ElemDesc) m_elementFlags.get("ILAYER"); 448 449 elemDesc.setAttr("SRC", ElemDesc.ATTRURL); 450 451 elemDesc = (ElemDesc) m_elementFlags.get("DIV"); 452 453 elemDesc.setAttr("SRC", ElemDesc.ATTRURL); 454 } 455 456 459 static private final ElemDesc m_dummy = new ElemDesc(0 | ElemDesc.BLOCK); 460 461 462 private boolean m_specialEscapeURLs = true; 463 464 465 private boolean m_omitMetaTag = false; 466 467 472 public void setSpecialEscapeURLs(boolean bool) 473 { 474 m_specialEscapeURLs = bool; 475 } 476 477 482 public void setOmitMetaTag(boolean bool) 483 { 484 m_omitMetaTag = bool; 485 } 486 487 496 public void setOutputFormat(Properties format) 497 { 498 499 m_specialEscapeURLs = 500 OutputPropertyUtils.getBooleanProperty( 501 OutputPropertiesFactory.S_USE_URL_ESCAPING, 502 format); 503 504 m_omitMetaTag = 505 OutputPropertyUtils.getBooleanProperty( 506 OutputPropertiesFactory.S_OMIT_META_TAG, 507 format); 508 509 super.setOutputFormat(format); 510 } 511 512 517 private final boolean getSpecialEscapeURLs() 518 { 519 return m_specialEscapeURLs; 520 } 521 522 527 private final boolean getOmitMetaTag() 528 { 529 return m_omitMetaTag; 530 } 531 532 540 public static final ElemDesc getElemDesc(String name) 541 { 542 545 Object obj = m_elementFlags.get(name); 546 if (null != obj) 547 return (ElemDesc)obj; 548 return m_dummy; 549 } 550 551 554 public ToHTMLStream() 555 { 556 557 super(); 558 m_charInfo = m_htmlcharInfo; 559 m_prefixMap = new NamespaceMappings(); 561 562 } 563 564 565 567 575 protected void startDocumentInternal() throws org.xml.sax.SAXException 576 { 577 super.startDocumentInternal(); 578 579 m_needToCallStartDocument = false; 580 m_needToOutputDocTypeDecl = true; 581 m_startNewLine = false; 582 setOmitXMLDeclaration(true); 583 584 if (true == m_needToOutputDocTypeDecl) 585 { 586 String doctypeSystem = getDoctypeSystem(); 587 String doctypePublic = getDoctypePublic(); 588 if ((null != doctypeSystem) || (null != doctypePublic)) 589 { 590 final java.io.Writer writer = m_writer; 591 try 592 { 593 writer.write("<!DOCTYPE HTML"); 594 595 if (null != doctypePublic) 596 { 597 writer.write(" PUBLIC \""); 598 writer.write(doctypePublic); 599 writer.write('"'); 600 } 601 602 if (null != doctypeSystem) 603 { 604 if (null == doctypePublic) 605 writer.write(" SYSTEM \""); 606 else 607 writer.write('"'); 608 609 writer.write(doctypeSystem); 610 writer.write('"'); 611 } 612 613 writer.write('>'); 614 outputLineSep(); 615 } 616 catch(IOException e) 617 { 618 throw new SAXException (e); 619 } 620 } 621 } 622 623 m_needToOutputDocTypeDecl = false; 624 } 625 626 634 public final void endDocument() throws org.xml.sax.SAXException 635 { 636 637 flushPending(); 638 if (m_doIndent && !m_isprevtext) 639 { 640 try 641 { 642 outputLineSep(); 643 } 644 catch(IOException e) 645 { 646 throw new SAXException (e); 647 } 648 } 649 650 flushWriter(); 651 if (m_tracer != null) 652 super.fireEndDoc(); 653 } 654 655 668 public void startElement( 669 String namespaceURI, 670 String localName, 671 String name, 672 Attributes atts) 673 throws org.xml.sax.SAXException 674 { 675 676 ElemContext elemContext = m_elemContext; 677 678 if (elemContext.m_startTagOpen) 680 { 681 closeStartTag(); 682 elemContext.m_startTagOpen = false; 683 } 684 else if (m_cdataTagOpen) 685 { 686 closeCDATA(); 687 m_cdataTagOpen = false; 688 } 689 else if (m_needToCallStartDocument) 690 { 691 startDocumentInternal(); 692 m_needToCallStartDocument = false; 693 } 694 695 696 if (null != namespaceURI && namespaceURI.length() > 0) 698 { 699 super.startElement(namespaceURI, localName, name, atts); 700 701 return; 702 } 703 704 try 705 { 706 ElemDesc elemDesc = getElemDesc(name); 707 int elemFlags = elemDesc.getFlags(); 708 709 if (m_doIndent) 711 { 712 713 boolean isBlockElement = (elemFlags & ElemDesc.BLOCK) != 0; 714 if (m_ispreserve) 715 m_ispreserve = false; 716 else if ( 717 (null != elemContext.m_elementName) 718 && (!m_inBlockElem 719 || isBlockElement) 720 ) 721 { 722 m_startNewLine = true; 723 724 indent(); 725 726 } 727 m_inBlockElem = !isBlockElement; 728 } 729 730 if (atts != null) 732 addAttributes(atts); 733 734 m_isprevtext = false; 735 final java.io.Writer writer = m_writer; 736 writer.write('<'); 737 writer.write(name); 738 739 740 741 if (m_tracer != null) 742 firePseudoAttributes(); 743 744 if ((elemFlags & ElemDesc.EMPTY) != 0) 745 { 746 m_elemContext = elemContext.push(); 749 752 m_elemContext.m_elementName = name; 753 m_elemContext.m_elementDesc = elemDesc; 754 return; 755 } 756 else 757 { 758 elemContext = elemContext.push(namespaceURI,localName,name); 759 m_elemContext = elemContext; 760 elemContext.m_elementDesc = elemDesc; 761 elemContext.m_isRaw = (elemFlags & ElemDesc.RAW) != 0; 762 } 763 764 765 if ((elemFlags & ElemDesc.HEADELEM) != 0) 766 { 767 closeStartTag(); 769 elemContext.m_startTagOpen = false; 770 if (!m_omitMetaTag) 771 { 772 if (m_doIndent) 773 indent(); 774 writer.write( 775 "<META http-equiv=\"Content-Type\" content=\"text/html; charset="); 776 String encoding = getEncoding(); 777 String encode = Encodings.getMimeEncoding(encoding); 778 writer.write(encode); 779 writer.write("\">"); 780 } 781 } 782 } 783 catch (IOException e) 784 { 785 throw new SAXException (e); 786 } 787 } 788 789 799 public final void endElement( 800 final String namespaceURI, 801 final String localName, 802 final String name) 803 throws org.xml.sax.SAXException 804 { 805 if (m_cdataTagOpen) 807 closeCDATA(); 808 809 if (null != namespaceURI && namespaceURI.length() > 0) 811 { 812 super.endElement(namespaceURI, localName, name); 813 814 return; 815 } 816 817 try 818 { 819 820 ElemContext elemContext = m_elemContext; 821 final ElemDesc elemDesc = elemContext.m_elementDesc; 822 final int elemFlags = elemDesc.getFlags(); 823 final boolean elemEmpty = (elemFlags & ElemDesc.EMPTY) != 0; 824 825 if (m_doIndent) 827 { 828 final boolean isBlockElement = (elemFlags&ElemDesc.BLOCK) != 0; 829 boolean shouldIndent = false; 830 831 if (m_ispreserve) 832 { 833 m_ispreserve = false; 834 } 835 else if (m_doIndent && (!m_inBlockElem || isBlockElement)) 836 { 837 m_startNewLine = true; 838 shouldIndent = true; 839 } 840 if (!elemContext.m_startTagOpen && shouldIndent) 841 indent(elemContext.m_currentElemDepth - 1); 842 m_inBlockElem = !isBlockElement; 843 } 844 845 final java.io.Writer writer = m_writer; 846 if (!elemContext.m_startTagOpen) 847 { 848 writer.write("</"); 849 writer.write(name); 850 writer.write('>'); 851 } 852 else 853 { 854 857 if (m_tracer != null) 858 super.fireStartElem(name); 859 860 int nAttrs = m_attributes.getLength(); 863 if (nAttrs > 0) 864 { 865 processAttributes(m_writer, nAttrs); 866 m_attributes.clear(); 868 } 869 if (!elemEmpty) 870 { 871 876 writer.write("></"); 877 writer.write(name); 878 writer.write('>'); 879 } 880 else 881 { 882 writer.write('>'); 883 } 884 } 885 886 if ((elemFlags & ElemDesc.WHITESPACESENSITIVE) != 0) 888 m_ispreserve = true; 889 m_isprevtext = false; 890 891 if (m_tracer != null) 893 super.fireEndElem(name); 894 895 if (elemEmpty) 897 { 898 m_elemContext = elemContext.m_prev; 902 return; 903 } 904 905 if (!elemContext.m_startTagOpen) 907 { 908 if (m_doIndent && !m_preserves.isEmpty()) 909 m_preserves.pop(); 910 } 911 m_elemContext = elemContext.m_prev; 912 } 914 catch (IOException e) 915 { 916 throw new SAXException (e); 917 } 918 } 919 920 930 protected void processAttribute( 931 java.io.Writer writer, 932 String name, 933 String value, 934 ElemDesc elemDesc) 935 throws IOException 936 { 937 writer.write(' '); 938 939 if ( ((value.length() == 0) || value.equalsIgnoreCase(name)) 940 && elemDesc != null 941 && elemDesc.isAttrFlagSet(name, ElemDesc.ATTREMPTY)) 942 { 943 writer.write(name); 944 } 945 else 946 { 947 writer.write(name); 951 writer.write("=\""); 952 if ( elemDesc != null 953 && elemDesc.isAttrFlagSet(name, ElemDesc.ATTRURL)) 954 writeAttrURI(writer, value, m_specialEscapeURLs); 955 else 956 writeAttrString(writer, value, this.getEncoding()); 957 writer.write('"'); 958 959 } 960 } 961 962 965 private boolean isASCIIDigit(char c) 966 { 967 return (c >= '0' && c <= '9'); 968 } 969 970 979 private static String makeHHString(int i) 980 { 981 String s = Integer.toHexString(i).toUpperCase(); 982 if (s.length() == 1) 983 { 984 s = "0" + s; 985 } 986 return s; 987 } 988 989 995 private boolean isHHSign(String str) 996 { 997 boolean sign = true; 998 try 999 { 1000 char r = (char) Integer.parseInt(str, 16); 1001 } 1002 catch (NumberFormatException e) 1003 { 1004 sign = false; 1005 } 1006 return sign; 1007 } 1008 1009 1019 public void writeAttrURI( 1020 final java.io.Writer writer, String string, boolean doURLEscaping) 1021 throws IOException 1022 { 1023 1038 final int end = string.length(); 1039 if (end > m_attrBuff.length) 1040 { 1041 m_attrBuff = new char[end*2 + 1]; 1042 } 1043 string.getChars(0,end, m_attrBuff, 0); 1044 final char[] chars = m_attrBuff; 1045 1046 int cleanStart = 0; 1047 int cleanLength = 0; 1048 1049 1050 char ch = 0; 1051 for (int i = 0; i < end; i++) 1052 { 1053 ch = chars[i]; 1054 1055 if ((ch < 32) || (ch > 126)) 1056 { 1057 if (cleanLength > 0) 1058 { 1059 writer.write(chars, cleanStart, cleanLength); 1060 cleanLength = 0; 1061 } 1062 if (doURLEscaping) 1063 { 1064 1068 if (ch <= 0x7F) 1075 { 1076 writer.write('%'); 1077 writer.write(makeHHString(ch)); 1078 } 1079 else if (ch <= 0x7FF) 1080 { 1081 int high = (ch >> 6) | 0xC0; 1084 int low = (ch & 0x3F) | 0x80; 1085 writer.write('%'); 1087 writer.write(makeHHString(high)); 1088 writer.write('%'); 1089 writer.write(makeHHString(low)); 1090 } 1091 else if (isUTF16Surrogate(ch)) { 1093 1100 int highSurrogate = ((int) ch) & 0x03FF; 1102 1103 int wwww = ((highSurrogate & 0x03C0) >> 6); 1108 int uuuuu = wwww + 1; 1109 1110 int zzzz = (highSurrogate & 0x003C) >> 2; 1112 1113 int yyyyyy = ((highSurrogate & 0x0003) << 4) & 0x30; 1115 1116 ch = chars[++i]; 1118 1119 int lowSurrogate = ((int) ch) & 0x03FF; 1121 1122 yyyyyy = yyyyyy | ((lowSurrogate & 0x03C0) >> 6); 1124 1125 int xxxxxx = (lowSurrogate & 0x003F); 1127 1128 int byte1 = 0xF0 | (uuuuu >> 2); int byte2 = 1130 0x80 | (((uuuuu & 0x03) << 4) & 0x30) | zzzz; 1131 int byte3 = 0x80 | yyyyyy; 1132 int byte4 = 0x80 | xxxxxx; 1133 1134 writer.write('%'); 1135 writer.write(makeHHString(byte1)); 1136 writer.write('%'); 1137 writer.write(makeHHString(byte2)); 1138 writer.write('%'); 1139 writer.write(makeHHString(byte3)); 1140 writer.write('%'); 1141 writer.write(makeHHString(byte4)); 1142 } 1143 else 1144 { 1145 int high = (ch >> 12) | 0xE0; int middle = ((ch & 0x0FC0) >> 6) | 0x80; 1147 int low = (ch & 0x3F) | 0x80; 1149 writer.write('%'); 1151 writer.write(makeHHString(high)); 1152 writer.write('%'); 1153 writer.write(makeHHString(middle)); 1154 writer.write('%'); 1155 writer.write(makeHHString(low)); 1156 } 1157 1158 } 1159 else if (escapingNotNeeded(ch)) 1160 { 1161 writer.write(ch); 1162 } 1163 else 1164 { 1165 writer.write("&#"); 1166 writer.write(Integer.toString(ch)); 1167 writer.write(';'); 1168 } 1169 cleanStart = i + 1; 1174 } 1175 else if (ch == '"') 1179 { 1180 1183 1186 1188 1190 if (cleanLength > 0) 1191 { 1192 writer.write(chars, cleanStart, cleanLength); 1193 cleanLength = 0; 1194 } 1195 1196 1197 if (doURLEscaping) 1199 writer.write("%22"); 1200 else 1201 writer.write("""); 1203 cleanStart = i + 1; 1206 } 1207 else 1208 { 1209 cleanLength++; 1212 } 1213 } 1214 1215 if (cleanLength > 1) 1218 { 1219 if (cleanStart == 0) 1223 writer.write(string); 1224 else 1225 writer.write(chars, cleanStart, cleanLength); 1226 } 1227 else if (cleanLength == 1) 1228 { 1229 writer.write(ch); 1232 } 1233 } 1234 1235 1244 public void writeAttrString( 1245 final java.io.Writer writer, String string, String encoding) 1246 throws IOException 1247 { 1248 final int end = string.length(); 1249 if (end > m_attrBuff.length) 1250 { 1251 m_attrBuff = new char[end * 2 + 1]; 1252 } 1253 string.getChars(0, end, m_attrBuff, 0); 1254 final char[] chars = m_attrBuff; 1255 1256 1257 1258 int cleanStart = 0; 1259 int cleanLength = 0; 1260 1261 char ch = 0; 1262 for (int i = 0; i < end; i++) 1263 { 1264 ch = chars[i]; 1265 1266 if (escapingNotNeeded(ch) && (!m_charInfo.isSpecialAttrChar(ch))) 1271 { 1272 cleanLength++; 1273 } 1274 else if ('<' == ch || '>' == ch) 1275 { 1276 cleanLength++; } 1278 else if ( 1279 ('&' == ch) && ((i + 1) < end) && ('{' == chars[i + 1])) 1280 { 1281 cleanLength++; } 1283 else 1284 { 1285 if (cleanLength > 0) 1286 { 1287 writer.write(chars,cleanStart,cleanLength); 1288 cleanLength = 0; 1289 } 1290 int pos = accumDefaultEntity(writer, ch, i, chars, end, false, false); 1291 1292 if (i != pos) 1293 { 1294 i = pos - 1; 1295 } 1296 else 1297 { 1298 if (isUTF16Surrogate(ch)) 1299 { 1300 1301 writeUTF16Surrogate(ch, chars, i, end); 1302 i++; } 1306 1307 1310 1318 String entityName = m_charInfo.getEntityNameForChar(ch); 1319 if (null != entityName) 1320 { 1321 writer.write('&'); 1322 writer.write(entityName); 1323 writer.write(';'); 1324 } 1325 else if (escapingNotNeeded(ch)) 1326 { 1327 writer.write(ch); } 1329 else 1330 { 1331 writer.write("&#"); 1332 writer.write(Integer.toString(ch)); 1333 writer.write(';'); 1334 } 1335 } 1336 cleanStart = i + 1; 1337 } 1338 } 1340 if (cleanLength > 1) 1343 { 1344 if (cleanStart == 0) 1348 writer.write(string); 1349 else 1350 writer.write(chars, cleanStart, cleanLength); 1351 } 1352 else if (cleanLength == 1) 1353 { 1354 writer.write(ch); 1357 } 1358 } 1359 1360 1361 1362 1389 public final void characters(char chars[], int start, int length) 1390 throws org.xml.sax.SAXException 1391 { 1392 1393 if (m_elemContext.m_isRaw) 1394 { 1395 try 1396 { 1397 if (m_elemContext.m_startTagOpen) 1398 { 1399 closeStartTag(); 1400 m_elemContext.m_startTagOpen = false; 1401 } 1402 m_ispreserve = true; 1403 1404 1409 writeNormalizedChars(chars, start, length, false, m_lineSepUse); 1412 1413 1415 if (m_tracer != null) 1417 super.fireCharEvent(chars, start, length); 1418 1419 return; 1420 } 1421 catch (IOException ioe) 1422 { 1423 throw new org.xml.sax.SAXException ( 1424 XMLMessages.createXMLMessage( 1425 XMLErrorResources.ER_OIERROR, 1426 null), 1427 ioe); 1428 } 1430 } 1431 else 1432 { 1433 super.characters(chars, start, length); 1434 } 1435 } 1436 1437 1464 public final void cdata(char ch[], int start, int length) 1465 throws org.xml.sax.SAXException 1466 { 1467 1468 if ((null != m_elemContext.m_elementName) 1469 && (m_elemContext.m_elementName.equalsIgnoreCase("SCRIPT") 1470 || m_elemContext.m_elementName.equalsIgnoreCase("STYLE"))) 1471 { 1472 try 1473 { 1474 if (m_elemContext.m_startTagOpen) 1475 { 1476 closeStartTag(); 1477 m_elemContext.m_startTagOpen = false; 1478 } 1479 1480 m_ispreserve = true; 1481 1482 if (shouldIndent()) 1483 indent(); 1484 1485 writeNormalizedChars(ch, start, length, true, m_lineSepUse); 1487 } 1488 catch (IOException ioe) 1489 { 1490 throw new org.xml.sax.SAXException ( 1491 XMLMessages.createXMLMessage( 1492 XMLErrorResources.ER_OIERROR, 1493 null), 1494 ioe); 1495 } 1497 } 1498 else 1499 { 1500 super.cdata(ch, start, length); 1501 } 1502 } 1503 1504 1515 public void processingInstruction(String target, String data) 1516 throws org.xml.sax.SAXException 1517 { 1518 1519 flushPending(); 1521 1522 if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING)) 1525 { 1526 startNonEscaping(); 1527 } 1528 else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING)) 1529 { 1530 endNonEscaping(); 1531 } 1532 else 1533 { 1534 try 1535 { 1536 if (m_elemContext.m_startTagOpen) 1537 { 1538 closeStartTag(); 1539 m_elemContext.m_startTagOpen = false; 1540 } 1541 else if (m_needToCallStartDocument) 1542 startDocumentInternal(); 1543 1544 if (shouldIndent()) 1545 indent(); 1546 1547 final java.io.Writer writer = m_writer; 1548 writer.write("<?"); 1550 writer.write(target); 1551 1552 if (data.length() > 0 && !Character.isSpaceChar(data.charAt(0))) 1553 writer.write(' '); 1554 1555 writer.write(data); writer.write('>'); 1559 if (m_elemContext.m_currentElemDepth <= 0) 1563 outputLineSep(); 1564 1565 m_startNewLine = true; 1566 } 1567 catch(IOException e) 1568 { 1569 throw new SAXException (e); 1570 } 1571 } 1572 1573 if (m_tracer != null) 1575 super.fireEscapingEvent(target, data); 1576 } 1577 1578 1585 public final void entityReference(String name) 1586 throws org.xml.sax.SAXException 1587 { 1588 try 1589 { 1590 1591 final java.io.Writer writer = m_writer; 1592 writer.write('&'); 1593 writer.write(name); 1594 writer.write(';'); 1595 1596 } catch(IOException e) 1597 { 1598 throw new SAXException (e); 1599 } 1600 } 1601 1604 public final void endElement(String elemName) throws SAXException 1605 { 1606 endElement(null, null, elemName); 1607 } 1608 1609 1620 public void processAttributes(java.io.Writer writer, int nAttrs) 1621 throws IOException ,SAXException 1622 { 1623 1626 for (int i = 0; i < nAttrs; i++) 1627 { 1628 processAttribute( 1629 writer, 1630 m_attributes.getQName(i), 1631 m_attributes.getValue(i), 1632 m_elemContext.m_elementDesc); 1633 } 1634 } 1635 1636 1642 protected void closeStartTag() throws SAXException 1643 { 1644 try 1645 { 1646 1647 if (m_tracer != null) 1649 super.fireStartElem(m_elemContext.m_elementName); 1650 1651 int nAttrs = m_attributes.getLength(); 1652 if (nAttrs>0) 1653 { 1654 processAttributes(m_writer, nAttrs); 1655 m_attributes.clear(); 1657 } 1658 1659 m_writer.write('>'); 1660 1661 1665 if (m_cdataSectionElements != null) 1666 m_elemContext.m_isCdataSection = isCdataSection(); 1667 if (m_doIndent) 1668 { 1669 m_isprevtext = false; 1670 m_preserves.push(m_ispreserve); 1671 } 1672 1673 } 1674 catch(IOException e) 1675 { 1676 throw new SAXException (e); 1677 } 1678 } 1679 1688 protected synchronized void init(OutputStream output, Properties format) 1689 throws UnsupportedEncodingException 1690 { 1691 if (null == format) 1692 { 1693 format = OutputPropertiesFactory.getDefaultMethodProperties(Method.HTML); 1694 } 1695 super.init(output,format, false); 1696 } 1697 1698 1709 public void setOutputStream(OutputStream output) 1710 { 1711 1712 try 1713 { 1714 Properties format; 1715 if (null == m_format) 1716 format = OutputPropertiesFactory.getDefaultMethodProperties(Method.HTML); 1717 else 1718 format = m_format; 1719 init(output, format, true); 1720 } 1721 catch (UnsupportedEncodingException uee) 1722 { 1723 1724 } 1726 } 1727 1738 public void namespaceAfterStartElement(String prefix, String uri) 1739 throws SAXException 1740 { 1741 if (m_elemContext.m_elementURI == null) 1743 { 1744 String prefix1 = getPrefixPart(m_elemContext.m_elementName); 1745 if (prefix1 == null && EMPTYSTRING.equals(prefix)) 1746 { 1747 m_elemContext.m_elementURI = uri; 1752 } 1753 } 1754 startPrefixMapping(prefix,uri,false); 1755 } 1756 1757 public void startDTD(String name, String publicId, String systemId) 1758 throws SAXException 1759 { 1760 m_inDTD = true; 1761 super.startDTD(name, publicId, systemId); 1762 } 1763 1764 1769 public void endDTD() throws org.xml.sax.SAXException 1770 { 1771 m_inDTD = false; 1772 1775 } 1776 1779 public void attributeDecl( 1780 String eName, 1781 String aName, 1782 String type, 1783 String valueDefault, 1784 String value) 1785 throws SAXException 1786 { 1787 } 1789 1790 1793 public void elementDecl(String name, String model) throws SAXException 1794 { 1795 } 1797 1800 public void internalEntityDecl(String name, String value) 1801 throws SAXException 1802 { 1803 } 1805 1808 public void externalEntityDecl( 1809 String name, 1810 String publicId, 1811 String systemId) 1812 throws SAXException 1813 { 1814 } 1816 1817 1827 public void addUniqueAttribute(String name, String value, int flags) 1828 throws SAXException 1829 { 1830 try 1831 { 1832 final java.io.Writer writer = m_writer; 1833 if ((flags & NO_BAD_CHARS) > 0 && m_htmlcharInfo.onlyQuotAmpLtGt) 1834 { 1835 writer.write(' '); 1841 writer.write(name); 1842 writer.write("=\""); 1843 writer.write(value); 1844 writer.write('"'); 1845 } 1846 else if ( 1847 (flags & HTML_ATTREMPTY) > 0 1848 && (value.length() == 0 || value.equalsIgnoreCase(name))) 1849 { 1850 writer.write(' '); 1851 writer.write(name); 1852 } 1853 else 1854 { 1855 writer.write(' '); 1856 writer.write(name); 1857 writer.write("=\""); 1858 if ((flags & HTML_ATTRURL) > 0) 1859 { 1860 writeAttrURI(writer, value, m_specialEscapeURLs); 1861 } 1862 else 1863 { 1864 writeAttrString(writer, value, this.getEncoding()); 1865 } 1866 writer.write('"'); 1867 } 1868 } catch (IOException e) { 1869 throw new SAXException (e); 1870 } 1871 } 1872 1873 public void comment(char ch[], int start, int length) 1874 throws SAXException 1875 { 1876 if (m_inDTD) 1878 return; 1879 super.comment(ch, start, length); 1880 } 1881 1882 public boolean reset() 1883 { 1884 boolean ret = super.reset(); 1885 if (!ret) 1886 return false; 1887 initToHTMLStream(); 1888 return true; 1889 } 1890 1891 private void initToHTMLStream() 1892 { 1893 m_inBlockElem = false; 1895 m_inDTD = false; 1896 m_omitMetaTag = false; 1898 m_specialEscapeURLs = true; 1899 } 1900} 1901 | Popular Tags |