< prev index next >

src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java

Print this page


   1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one
   7  * or more contributor license agreements. See the NOTICE file
   8  * distributed with this work for additional information
   9  * regarding copyright ownership. The ASF licenses this file
  10  * to you under the Apache License, Version 2.0 (the  "License");
  11  * you may not use this file except in compliance with the License.
  12  * You may obtain a copy of the License at
  13  *
  14  *     http://www.apache.org/licenses/LICENSE-2.0
  15  *
  16  * Unless required by applicable law or agreed to in writing, software
  17  * distributed under the License is distributed on an "AS IS" BASIS,
  18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19  * See the License for the specific language governing permissions and
  20  * limitations under the License.
  21  */
  22 /*
  23  * $Id: ToHTMLStream.java,v 1.2.4.1 2005/09/15 08:15:26 suresh_emailid Exp $
  24  */
  25 package com.sun.org.apache.xml.internal.serializer;
  26 
  27 import java.io.IOException;
  28 import java.io.OutputStream;
  29 import java.io.UnsupportedEncodingException;
  30 import java.util.Properties;
  31 
  32 import javax.xml.transform.Result;
  33 
  34 import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
  35 import com.sun.org.apache.xml.internal.serializer.utils.Utils;
  36 import org.xml.sax.Attributes;
  37 import org.xml.sax.SAXException;
  38 



  39 /**
  40  * This serializer takes a series of SAX or
  41  * SAX-like events and writes its output
  42  * to the given stream.
  43  *
  44  * This class is not a public API, it is public
  45  * because it is used from another package.
  46  *
  47  * @xsl.usage internal
  48  */
  49 public final class ToHTMLStream extends ToStream
  50 {
  51 
  52     /** This flag is set while receiving events from the DTD */
  53     protected boolean m_inDTD = false;
  54 
  55     /** True if the current element is a block element.  (seems like
  56      *  this needs to be a stack. -sb). */
  57     private boolean m_inBlockElem = false;
  58 
  59     /**
  60      * Map that tells which XML characters should have special treatment, and it
  61      *  provides character to entity name lookup.
  62      */
  63     private static final CharInfo m_htmlcharInfo =
  64 //        new CharInfo(CharInfo.HTML_ENTITIES_RESOURCE);
  65         CharInfo.getCharInfoInternal(CharInfo.HTML_ENTITIES_RESOURCE, Method.HTML);
  66 
  67     /** A digital search trie for fast, case insensitive lookup of ElemDesc objects. */
  68     static final Trie m_elementFlags = new Trie();
  69 
  70     static {
  71         initTagReference(m_elementFlags);
  72     }
  73     static void initTagReference(Trie m_elementFlags) {
  74 
  75         // HTML 4.0 loose DTD
  76         m_elementFlags.put("BASEFONT", new ElemDesc(0 | ElemDesc.EMPTY));
  77         m_elementFlags.put(


 706                 catch(IOException e)
 707                 {
 708                     throw new SAXException(e);
 709                 }
 710             }
 711         }
 712 
 713         m_needToOutputDocTypeDecl = false;
 714     }
 715 
 716     /**
 717      * Receive notification of the end of a document.
 718      *
 719      * @throws org.xml.sax.SAXException Any SAX exception, possibly
 720      *            wrapping another exception.
 721      *
 722      * @throws org.xml.sax.SAXException
 723      */
 724     public final void endDocument() throws org.xml.sax.SAXException
 725     {
 726 
 727         flushPending();
 728         if (m_doIndent && !m_isprevtext)
 729         {
 730             try
 731             {
 732             outputLineSep();
 733             }
 734             catch(IOException e)
 735             {
 736                 throw new SAXException(e);
 737             }
 738         }
 739 
 740         flushWriter();
 741         if (m_tracer != null)
 742             super.fireEndDoc();
 743     }
 744 
 745     /**


















 746      *  Receive notification of the beginning of an element.
 747      *
 748      *
 749      *  @param namespaceURI
 750      *  @param localName
 751      *  @param name The element type name.
 752      *  @param atts The attributes attached to the element, if any.
 753      *  @throws org.xml.sax.SAXException Any SAX exception, possibly
 754      *             wrapping another exception.


 755      *  @see #endElement
 756      *  @see org.xml.sax.AttributeList
 757      */
 758     public void startElement(
 759         String namespaceURI,
 760         String localName,
 761         String name,
 762         Attributes atts)
 763         throws org.xml.sax.SAXException
 764     {
 765 


 766         ElemContext elemContext = m_elemContext;
 767 
 768         // clean up any pending things first
 769         if (elemContext.m_startTagOpen)
 770         {
 771             closeStartTag();
 772             elemContext.m_startTagOpen = false;
 773         }
 774         else if (m_cdataTagOpen)
 775         {
 776             closeCDATA();
 777             m_cdataTagOpen = false;
 778         }
 779         else if (m_needToCallStartDocument)
 780         {
 781             startDocumentInternal();
 782             m_needToCallStartDocument = false;
 783         }
 784 
 785 
 786         // if this element has a namespace then treat it like XML
 787         if (null != namespaceURI && namespaceURI.length() > 0)
 788         {
 789             super.startElement(namespaceURI, localName, name, atts);
 790 
 791             return;
 792         }
 793 
 794         try
 795         {
 796             // getElemDesc2(name) is faster than getElemDesc(name)
 797             ElemDesc elemDesc = getElemDesc2(name);
 798             int elemFlags = elemDesc.getFlags();
 799 
 800             // deal with indentation issues first
 801             if (m_doIndent)
 802             {
 803 
 804                 boolean isBlockElement = (elemFlags & ElemDesc.BLOCK) != 0;
 805                 if (m_ispreserve)
 806                     m_ispreserve = false;
 807                 else if (
 808                     (null != elemContext.m_elementName)
 809                     && (!m_inBlockElem
 810                         || isBlockElement) /* && !isWhiteSpaceSensitive */
 811                     )
 812                 {
 813                     m_startNewLine = true;
 814 
 815                     indent();
 816 
 817                 }
 818                 m_inBlockElem = !isBlockElement;
 819             }
 820 
 821             // save any attributes for later processing
 822             if (atts != null)
 823                 addAttributes(atts);
 824 
 825             m_isprevtext = false;
 826             final java.io.Writer writer = m_writer;
 827             writer.write('<');
 828             writer.write(name);
 829 
 830 

 831 
 832             if (m_tracer != null)
 833                 firePseudoAttributes();
 834 
 835             if ((elemFlags & ElemDesc.EMPTY) != 0)
 836             {
 837                 // an optimization for elements which are expected
 838                 // to be empty.
 839                 m_elemContext = elemContext.push();
 840                 /* XSLTC sometimes calls namespaceAfterStartElement()
 841                  * so we need to remember the name
 842                  */
 843                 m_elemContext.m_elementName = name;
 844                 m_elemContext.m_elementDesc = elemDesc;
 845                 return;
 846             }
 847             else
 848             {
 849                 elemContext = elemContext.push(namespaceURI,localName,name);
 850                 m_elemContext = elemContext;
 851                 elemContext.m_elementDesc = elemDesc;
 852                 elemContext.m_isRaw = (elemFlags & ElemDesc.RAW) != 0;









 853             }
 854 
 855 
 856             if ((elemFlags & ElemDesc.HEADELEM) != 0)
 857             {
 858                 // This is the <HEAD> element, do some special processing
 859                 closeStartTag();
 860                 elemContext.m_startTagOpen = false;
 861                 if (!m_omitMetaTag)
 862                 {
 863                     if (m_doIndent)
 864                         indent();
 865                     writer.write(
 866                         "<META http-equiv=\"Content-Type\" content=\"text/html; charset=");
 867                     String encoding = getEncoding();
 868                     String encode = Encodings.getMimeEncoding(encoding);
 869                     writer.write(encode);
 870                     writer.write("\">");
 871                 }
 872             }


 876             throw new SAXException(e);
 877         }
 878     }
 879 
 880     /**
 881      *  Receive notification of the end of an element.
 882      *
 883      *
 884      *  @param namespaceURI
 885      *  @param localName
 886      *  @param name The element type name
 887      *  @throws org.xml.sax.SAXException Any SAX exception, possibly
 888      *             wrapping another exception.
 889      */
 890     public final void endElement(
 891         final String namespaceURI,
 892         final String localName,
 893         final String name)
 894         throws org.xml.sax.SAXException
 895     {

 896         // deal with any pending issues
 897         if (m_cdataTagOpen)
 898             closeCDATA();
 899 
 900         // if the element has a namespace, treat it like XML, not HTML
 901         if (null != namespaceURI && namespaceURI.length() > 0)
 902         {
 903             super.endElement(namespaceURI, localName, name);
 904 
 905             return;
 906         }
 907 
 908         try
 909         {
 910 
 911             ElemContext elemContext = m_elemContext;
 912             final ElemDesc elemDesc = elemContext.m_elementDesc;
 913             final int elemFlags = elemDesc.getFlags();
 914             final boolean elemEmpty = (elemFlags & ElemDesc.EMPTY) != 0;
 915 
 916             // deal with any indentation issues
 917             if (m_doIndent)
 918             {
 919                 final boolean isBlockElement = (elemFlags&ElemDesc.BLOCK) != 0;
 920                 boolean shouldIndent = false;
 921 
 922                 if (m_ispreserve)
 923                 {
 924                     m_ispreserve = false;
 925                 }
 926                 else if (m_doIndent && (!m_inBlockElem || isBlockElement))
 927                 {
 928                     m_startNewLine = true;
 929                     shouldIndent = true;
 930                 }
 931                 if (!elemContext.m_startTagOpen && shouldIndent)
 932                     indent(elemContext.m_currentElemDepth - 1);
 933                 m_inBlockElem = !isBlockElement;

 934             }
 935 
 936             final java.io.Writer writer = m_writer;
 937             if (!elemContext.m_startTagOpen)
 938             {
 939                 writer.write("</");
 940                 writer.write(name);
 941                 writer.write('>');
 942             }
 943             else
 944             {
 945                 // the start-tag open when this method was called,
 946                 // so we need to process it now.
 947 
 948                 if (m_tracer != null)
 949                     super.fireStartElem(name);
 950 
 951                 // the starting tag was still open when we received this endElement() call
 952                 // so we need to process any gathered attributes NOW, before they go away.
 953                 int nAttrs = m_attributes.getLength();


 957                     // clear attributes object for re-use with next element
 958                     m_attributes.clear();
 959                 }
 960                 if (!elemEmpty)
 961                 {
 962                     // As per Dave/Paul recommendation 12/06/2000
 963                     // if (shouldIndent)
 964                     // writer.write('>');
 965                     //  indent(m_currentIndent);
 966 
 967                     writer.write("></");
 968                     writer.write(name);
 969                     writer.write('>');
 970                 }
 971                 else
 972                 {
 973                     writer.write('>');
 974                 }
 975             }
 976 

 977             // clean up because the element has ended
 978             if ((elemFlags & ElemDesc.WHITESPACESENSITIVE) != 0)
 979                 m_ispreserve = true;
 980             m_isprevtext = false;
 981 
 982             // fire off the end element event
 983             if (m_tracer != null)
 984                 super.fireEndElem(name);
 985 
 986             // OPTIMIZE-EMPTY
 987             if (elemEmpty)
 988             {
 989                 // a quick exit if the HTML element had no children.
 990                 // This block of code can be removed if the corresponding block of code
 991                 // in startElement() also labeled with "OPTIMIZE-EMPTY" is also removed
 992                 m_elemContext = elemContext.m_prev;
 993                 return;
 994             }
 995 
 996             // some more clean because the element has ended.


1494 
1495         if (m_elemContext.m_isRaw)
1496         {
1497             try
1498             {
1499                 if (m_elemContext.m_startTagOpen)
1500                 {
1501                     closeStartTag();
1502                     m_elemContext.m_startTagOpen = false;
1503                 }
1504                 m_ispreserve = true;
1505 
1506 //              With m_ispreserve just set true it looks like shouldIndent()
1507 //              will always return false, so drop any possible indentation.
1508 //              if (shouldIndent())
1509 //                  indent();
1510 
1511                 // writer.write("<![CDATA[");
1512                 // writer.write(chars, start, length);
1513                 writeNormalizedChars(chars, start, length, false, m_lineSepUse);
1514 
1515                 // writer.write("]]>");
1516 
1517                 // time to generate characters event
1518                 if (m_tracer != null)
1519                     super.fireCharEvent(chars, start, length);
1520 
1521                 return;
1522             }
1523             catch (IOException ioe)
1524             {
1525                 throw new org.xml.sax.SAXException(
1526                     Utils.messages.createMessage(
1527                         MsgKey.ER_OIERROR,
1528                         null),
1529                     ioe);
1530                 //"IO error", ioe);
1531             }
1532         }
1533         else
1534         {


1549      *  <p>The application must not attempt to read from the array
1550      *  outside of the specified range.</p>
1551      *
1552      *  <p>Note that some parsers will report whitespace using the
1553      *  ignorableWhitespace() method rather than this one (validating
1554      *  parsers must do so).</p>
1555      *
1556      *  @param ch The characters from the XML document.
1557      *  @param start The start position in the array.
1558      *  @param length The number of characters to read from the array.
1559      *  @throws org.xml.sax.SAXException Any SAX exception, possibly
1560      *             wrapping another exception.
1561      *  @see #ignorableWhitespace
1562      *  @see org.xml.sax.Locator
1563      *
1564      * @throws org.xml.sax.SAXException
1565      */
1566     public final void cdata(char ch[], int start, int length)
1567         throws org.xml.sax.SAXException
1568     {
1569 
1570         if ((null != m_elemContext.m_elementName)
1571             && (m_elemContext.m_elementName.equalsIgnoreCase("SCRIPT")
1572                 || m_elemContext.m_elementName.equalsIgnoreCase("STYLE")))
1573         {
1574             try
1575             {
1576                 if (m_elemContext.m_startTagOpen)
1577                 {
1578                     closeStartTag();
1579                     m_elemContext.m_startTagOpen = false;
1580                 }
1581 
1582                 m_ispreserve = true;
1583 
1584                 if (shouldIndent())
1585                     indent();
1586 
1587                 // writer.write(ch, start, length);
1588                 writeNormalizedChars(ch, start, length, true, m_lineSepUse);
1589             }


1600         else
1601         {
1602             super.cdata(ch, start, length);
1603         }
1604     }
1605 
1606     /**
1607      *  Receive notification of a processing instruction.
1608      *
1609      *  @param target The processing instruction target.
1610      *  @param data The processing instruction data, or null if
1611      *         none was supplied.
1612      *  @throws org.xml.sax.SAXException Any SAX exception, possibly
1613      *             wrapping another exception.
1614      *
1615      * @throws org.xml.sax.SAXException
1616      */
1617     public void processingInstruction(String target, String data)
1618         throws org.xml.sax.SAXException
1619     {
1620 

1621         // Process any pending starDocument and startElement first.
1622         flushPending();
1623 
1624         // Use a fairly nasty hack to tell if the next node is supposed to be
1625         // unescaped text.
1626         if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING))
1627         {
1628             startNonEscaping();
1629         }
1630         else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING))
1631         {
1632             endNonEscaping();
1633         }
1634         else
1635         {
1636             try
1637             {
1638             if (m_elemContext.m_startTagOpen)
1639             {
1640                 closeStartTag();


1928     public void comment(char ch[], int start, int length)
1929             throws SAXException
1930     {
1931         // The internal DTD subset is not serialized by the ToHTMLStream serializer
1932         if (m_inDTD)
1933             return;
1934         super.comment(ch, start, length);
1935     }
1936 
1937     public boolean reset()
1938     {
1939         boolean ret = super.reset();
1940         if (!ret)
1941             return false;
1942         initToHTMLStream();
1943         return true;
1944     }
1945 
1946     private void initToHTMLStream()
1947     {
1948 //        m_elementDesc = null;
1949         m_inBlockElem = false;
1950         m_inDTD = false;
1951 //        m_isRawStack.clear();
1952         m_omitMetaTag = false;
1953         m_specialEscapeURLs = true;
1954     }
1955 
1956     static class Trie
1957     {
1958         /**
1959          * A digital search trie for 7-bit ASCII text
1960          * The API is a subset of java.util.Hashtable
1961          * The key must be a 7-bit ASCII string
1962          * The value may be any Java Object
1963          * One can get an object stored in a trie from its key,
1964          * but the search is either case sensitive or case
1965          * insensitive to the characters in the key, and this
1966          * choice of sensitivity or insensitivity is made when
1967          * the Trie is created, before any objects are put in it.
1968          *
1969          * This class is a copy of the one in com.sun.org.apache.xml.internal.utils.
1970          * It exists to cut the serializers dependancy on that package.
1971          *


   1 /*
   2  * Copyright (c) 2014, 2016 Oracle and/or its affiliates. All rights reserved.

   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at

  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 


  21 package com.sun.org.apache.xml.internal.serializer;
  22 
  23 import java.io.IOException;


  24 import java.util.Properties;
  25 
  26 import javax.xml.transform.Result;
  27 


  28 import org.xml.sax.Attributes;
  29 import org.xml.sax.SAXException;
  30 
  31 import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
  32 import com.sun.org.apache.xml.internal.serializer.utils.Utils;
  33 
  34 /**
  35  * This serializer takes a series of SAX or
  36  * SAX-like events and writes its output
  37  * to the given stream.
  38  *
  39  * This class is not a public API, it is public
  40  * because it is used from another package.
  41  *
  42  * @xsl.usage internal
  43  */
  44 public final class ToHTMLStream extends ToStream
  45 {
  46 
  47     /** This flag is set while receiving events from the DTD */
  48     protected boolean m_inDTD = false;
  49 
  50     /** True if the previous element is a block element. */
  51     private boolean m_isprevblock = false;

  52 
  53     /**
  54      * Map that tells which XML characters should have special treatment, and it
  55      *  provides character to entity name lookup.
  56      */
  57     private static final CharInfo m_htmlcharInfo =
  58 //        new CharInfo(CharInfo.HTML_ENTITIES_RESOURCE);
  59         CharInfo.getCharInfoInternal(CharInfo.HTML_ENTITIES_RESOURCE, Method.HTML);
  60 
  61     /** A digital search trie for fast, case insensitive lookup of ElemDesc objects. */
  62     static final Trie m_elementFlags = new Trie();
  63 
  64     static {
  65         initTagReference(m_elementFlags);
  66     }
  67     static void initTagReference(Trie m_elementFlags) {
  68 
  69         // HTML 4.0 loose DTD
  70         m_elementFlags.put("BASEFONT", new ElemDesc(0 | ElemDesc.EMPTY));
  71         m_elementFlags.put(


 700                 catch(IOException e)
 701                 {
 702                     throw new SAXException(e);
 703                 }
 704             }
 705         }
 706 
 707         m_needToOutputDocTypeDecl = false;
 708     }
 709 
 710     /**
 711      * Receive notification of the end of a document.
 712      *
 713      * @throws org.xml.sax.SAXException Any SAX exception, possibly
 714      *            wrapping another exception.
 715      *
 716      * @throws org.xml.sax.SAXException
 717      */
 718     public final void endDocument() throws org.xml.sax.SAXException
 719     {
 720         flushCharactersBuffer();
 721         flushPending();
 722         if (m_doIndent && !m_isprevtext)
 723         {
 724             try
 725             {
 726             outputLineSep();
 727             }
 728             catch(IOException e)
 729             {
 730                 throw new SAXException(e);
 731             }
 732         }
 733 
 734         flushWriter();
 735         if (m_tracer != null)
 736             super.fireEndDoc();
 737     }
 738 
 739     /**
 740      * If the previous is an inline element, won't insert a new line before the
 741      * text.
 742      *
 743      */
 744     protected boolean shouldIndentForText() {
 745         return super.shouldIndentForText() && m_isprevblock;
 746     }
 747 
 748     /**
 749      * Only check m_doIndent, disregard m_ispreserveSpace.
 750      *
 751      * @return True if the content should be formatted.
 752      */
 753     protected boolean shouldFormatOutput() {
 754         return m_doIndent;
 755     }
 756 
 757     /**
 758      * Receive notification of the beginning of an element.
 759      *
 760      *
 761      * @param namespaceURI
 762      * @param localName
 763      * @param name
 764      *            The element type name.
 765      * @param atts
 766      *            The attributes attached to the element, if any.
 767      * @throws org.xml.sax.SAXException
 768      *             Any SAX exception, possibly wrapping another exception.
 769      * @see #endElement
 770      * @see org.xml.sax.AttributeList
 771      */
 772     public void startElement(
 773         String namespaceURI,
 774         String localName,
 775         String name,
 776         Attributes atts)
 777         throws SAXException
 778     {
 779         // will add extra one if having namespace but no matter
 780         m_childNodeNum++;
 781         flushCharactersBuffer();
 782         ElemContext elemContext = m_elemContext;
 783 
 784         // clean up any pending things first
 785         if (elemContext.m_startTagOpen)
 786         {
 787             closeStartTag();
 788             elemContext.m_startTagOpen = false;
 789         }
 790         else if (m_cdataTagOpen)
 791         {
 792             closeCDATA();
 793             m_cdataTagOpen = false;
 794         }
 795         else if (m_needToCallStartDocument)
 796         {
 797             startDocumentInternal();
 798             m_needToCallStartDocument = false;
 799         }
 800 
 801 
 802         // if this element has a namespace then treat it like XML
 803         if (null != namespaceURI && namespaceURI.length() > 0)
 804         {
 805             super.startElement(namespaceURI, localName, name, atts);
 806 
 807             return;
 808         }
 809 
 810         try
 811         {
 812             // getElemDesc2(name) is faster than getElemDesc(name)
 813             ElemDesc elemDesc = getElemDesc2(name);
 814             int elemFlags = elemDesc.getFlags();
 815 
 816             // deal with indentation issues first
 817             if (m_doIndent)
 818             {

 819                 boolean isBlockElement = (elemFlags & ElemDesc.BLOCK) != 0;
 820                 if ((elemContext.m_elementName != null)
 821                         // If this element is a block element,
 822                         // or if this is not a block element, then if the
 823                         // previous is neither a text nor an inline
 824                         && (isBlockElement || (!(m_isprevtext || !m_isprevblock))))


 825                 {
 826                     m_startNewLine = true;
 827 
 828                     indent();

 829                 }
 830                 m_isprevblock = isBlockElement;
 831             }
 832 
 833             // save any attributes for later processing
 834             if (atts != null)
 835                 addAttributes(atts);
 836 
 837             m_isprevtext = false;
 838             final java.io.Writer writer = m_writer;
 839             writer.write('<');
 840             writer.write(name);
 841 
 842             m_childNodeNumStack.push(m_childNodeNum);
 843             m_childNodeNum = 0;
 844 
 845             if (m_tracer != null)
 846                 firePseudoAttributes();
 847 
 848             if ((elemFlags & ElemDesc.EMPTY) != 0)
 849             {
 850                 // an optimization for elements which are expected
 851                 // to be empty.
 852                 m_elemContext = elemContext.push();
 853                 /* XSLTC sometimes calls namespaceAfterStartElement()
 854                  * so we need to remember the name
 855                  */
 856                 m_elemContext.m_elementName = name;
 857                 m_elemContext.m_elementDesc = elemDesc;
 858                 return;
 859             }
 860             else
 861             {
 862                 elemContext = elemContext.push(namespaceURI,localName,name);
 863                 m_elemContext = elemContext;
 864                 elemContext.m_elementDesc = elemDesc;
 865                 elemContext.m_isRaw = (elemFlags & ElemDesc.RAW) != 0;
 866 
 867                 // set m_startNewLine for the next element
 868                 if (m_doIndent) {
 869                     // elemFlags is equivalent to m_elemContext.m_elementDesc.getFlags(),
 870                     // in this branch m_elemContext.m_elementName is not null
 871                     boolean isBlockElement = (elemFlags & ElemDesc.BLOCK) != 0;
 872                     if (isBlockElement)
 873                         m_startNewLine = true;
 874                 }
 875             }
 876 
 877 
 878             if ((elemFlags & ElemDesc.HEADELEM) != 0)
 879             {
 880                 // This is the <HEAD> element, do some special processing
 881                 closeStartTag();
 882                 elemContext.m_startTagOpen = false;
 883                 if (!m_omitMetaTag)
 884                 {
 885                     if (m_doIndent)
 886                         indent();
 887                     writer.write(
 888                         "<META http-equiv=\"Content-Type\" content=\"text/html; charset=");
 889                     String encoding = getEncoding();
 890                     String encode = Encodings.getMimeEncoding(encoding);
 891                     writer.write(encode);
 892                     writer.write("\">");
 893                 }
 894             }


 898             throw new SAXException(e);
 899         }
 900     }
 901 
 902     /**
 903      *  Receive notification of the end of an element.
 904      *
 905      *
 906      *  @param namespaceURI
 907      *  @param localName
 908      *  @param name The element type name
 909      *  @throws org.xml.sax.SAXException Any SAX exception, possibly
 910      *             wrapping another exception.
 911      */
 912     public final void endElement(
 913         final String namespaceURI,
 914         final String localName,
 915         final String name)
 916         throws org.xml.sax.SAXException
 917     {
 918         flushCharactersBuffer();
 919         // deal with any pending issues
 920         if (m_cdataTagOpen)
 921             closeCDATA();
 922 
 923         // if the element has a namespace, treat it like XML, not HTML
 924         if (null != namespaceURI && namespaceURI.length() > 0)
 925         {
 926             super.endElement(namespaceURI, localName, name);
 927 
 928             return;
 929         }
 930 
 931         try
 932         {
 933 
 934             ElemContext elemContext = m_elemContext;
 935             final ElemDesc elemDesc = elemContext.m_elementDesc;
 936             final int elemFlags = elemDesc.getFlags();
 937             final boolean elemEmpty = (elemFlags & ElemDesc.EMPTY) != 0;
 938 
 939             // deal with any indentation issues
 940             if (m_doIndent)
 941             {
 942                 final boolean isBlockElement = (elemFlags&ElemDesc.BLOCK) != 0;
 943                 boolean shouldIndent = false;
 944 
 945                 // If this element is a block element,
 946                 // or if this is not a block element, then if the previous is
 947                 // neither a text nor an inline
 948                 if (isBlockElement || (!(m_isprevtext || !m_isprevblock)))

 949                 {
 950                     m_startNewLine = true;
 951                     shouldIndent = true;
 952                 }
 953                 if (!elemContext.m_startTagOpen && shouldIndent && (m_childNodeNum > 1 || !m_isprevtext))
 954                     indent(elemContext.m_currentElemDepth - 1);
 955 
 956                 m_isprevblock = isBlockElement;
 957             }
 958 
 959             final java.io.Writer writer = m_writer;
 960             if (!elemContext.m_startTagOpen)
 961             {
 962                 writer.write("</");
 963                 writer.write(name);
 964                 writer.write('>');
 965             }
 966             else
 967             {
 968                 // the start-tag open when this method was called,
 969                 // so we need to process it now.
 970 
 971                 if (m_tracer != null)
 972                     super.fireStartElem(name);
 973 
 974                 // the starting tag was still open when we received this endElement() call
 975                 // so we need to process any gathered attributes NOW, before they go away.
 976                 int nAttrs = m_attributes.getLength();


 980                     // clear attributes object for re-use with next element
 981                     m_attributes.clear();
 982                 }
 983                 if (!elemEmpty)
 984                 {
 985                     // As per Dave/Paul recommendation 12/06/2000
 986                     // if (shouldIndent)
 987                     // writer.write('>');
 988                     //  indent(m_currentIndent);
 989 
 990                     writer.write("></");
 991                     writer.write(name);
 992                     writer.write('>');
 993                 }
 994                 else
 995                 {
 996                     writer.write('>');
 997                 }
 998             }
 999 
1000             m_childNodeNum = m_childNodeNumStack.pop();
1001             // clean up because the element has ended
1002             if ((elemFlags & ElemDesc.WHITESPACESENSITIVE) != 0)
1003                 m_ispreserve = true;
1004             m_isprevtext = false;
1005 
1006             // fire off the end element event
1007             if (m_tracer != null)
1008                 super.fireEndElem(name);
1009 
1010             // OPTIMIZE-EMPTY
1011             if (elemEmpty)
1012             {
1013                 // a quick exit if the HTML element had no children.
1014                 // This block of code can be removed if the corresponding block of code
1015                 // in startElement() also labeled with "OPTIMIZE-EMPTY" is also removed
1016                 m_elemContext = elemContext.m_prev;
1017                 return;
1018             }
1019 
1020             // some more clean because the element has ended.


1518 
1519         if (m_elemContext.m_isRaw)
1520         {
1521             try
1522             {
1523                 if (m_elemContext.m_startTagOpen)
1524                 {
1525                     closeStartTag();
1526                     m_elemContext.m_startTagOpen = false;
1527                 }
1528                 m_ispreserve = true;
1529 
1530 //              With m_ispreserve just set true it looks like shouldIndent()
1531 //              will always return false, so drop any possible indentation.
1532 //              if (shouldIndent())
1533 //                  indent();
1534 
1535                 // writer.write("<![CDATA[");
1536                 // writer.write(chars, start, length);
1537                 writeNormalizedChars(chars, start, length, false, m_lineSepUse);
1538                 m_isprevtext = true;
1539                 // writer.write("]]>");
1540 
1541                 // time to generate characters event
1542                 if (m_tracer != null)
1543                     super.fireCharEvent(chars, start, length);
1544 
1545                 return;
1546             }
1547             catch (IOException ioe)
1548             {
1549                 throw new org.xml.sax.SAXException(
1550                     Utils.messages.createMessage(
1551                         MsgKey.ER_OIERROR,
1552                         null),
1553                     ioe);
1554                 //"IO error", ioe);
1555             }
1556         }
1557         else
1558         {


1573      *  <p>The application must not attempt to read from the array
1574      *  outside of the specified range.</p>
1575      *
1576      *  <p>Note that some parsers will report whitespace using the
1577      *  ignorableWhitespace() method rather than this one (validating
1578      *  parsers must do so).</p>
1579      *
1580      *  @param ch The characters from the XML document.
1581      *  @param start The start position in the array.
1582      *  @param length The number of characters to read from the array.
1583      *  @throws org.xml.sax.SAXException Any SAX exception, possibly
1584      *             wrapping another exception.
1585      *  @see #ignorableWhitespace
1586      *  @see org.xml.sax.Locator
1587      *
1588      * @throws org.xml.sax.SAXException
1589      */
1590     public final void cdata(char ch[], int start, int length)
1591         throws org.xml.sax.SAXException
1592     {

1593         if ((null != m_elemContext.m_elementName)
1594             && (m_elemContext.m_elementName.equalsIgnoreCase("SCRIPT")
1595                 || m_elemContext.m_elementName.equalsIgnoreCase("STYLE")))
1596         {
1597             try
1598             {
1599                 if (m_elemContext.m_startTagOpen)
1600                 {
1601                     closeStartTag();
1602                     m_elemContext.m_startTagOpen = false;
1603                 }
1604 
1605                 m_ispreserve = true;
1606 
1607                 if (shouldIndent())
1608                     indent();
1609 
1610                 // writer.write(ch, start, length);
1611                 writeNormalizedChars(ch, start, length, true, m_lineSepUse);
1612             }


1623         else
1624         {
1625             super.cdata(ch, start, length);
1626         }
1627     }
1628 
1629     /**
1630      *  Receive notification of a processing instruction.
1631      *
1632      *  @param target The processing instruction target.
1633      *  @param data The processing instruction data, or null if
1634      *         none was supplied.
1635      *  @throws org.xml.sax.SAXException Any SAX exception, possibly
1636      *             wrapping another exception.
1637      *
1638      * @throws org.xml.sax.SAXException
1639      */
1640     public void processingInstruction(String target, String data)
1641         throws org.xml.sax.SAXException
1642     {
1643         m_childNodeNum++;
1644         flushCharactersBuffer();
1645         // Process any pending starDocument and startElement first.
1646         flushPending();
1647 
1648         // Use a fairly nasty hack to tell if the next node is supposed to be
1649         // unescaped text.
1650         if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING))
1651         {
1652             startNonEscaping();
1653         }
1654         else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING))
1655         {
1656             endNonEscaping();
1657         }
1658         else
1659         {
1660             try
1661             {
1662             if (m_elemContext.m_startTagOpen)
1663             {
1664                 closeStartTag();


1952     public void comment(char ch[], int start, int length)
1953             throws SAXException
1954     {
1955         // The internal DTD subset is not serialized by the ToHTMLStream serializer
1956         if (m_inDTD)
1957             return;
1958         super.comment(ch, start, length);
1959     }
1960 
1961     public boolean reset()
1962     {
1963         boolean ret = super.reset();
1964         if (!ret)
1965             return false;
1966         initToHTMLStream();
1967         return true;
1968     }
1969 
1970     private void initToHTMLStream()
1971     {
1972         m_isprevblock = false;

1973         m_inDTD = false;

1974         m_omitMetaTag = false;
1975         m_specialEscapeURLs = true;
1976     }
1977 
1978     static class Trie
1979     {
1980         /**
1981          * A digital search trie for 7-bit ASCII text
1982          * The API is a subset of java.util.Hashtable
1983          * The key must be a 7-bit ASCII string
1984          * The value may be any Java Object
1985          * One can get an object stored in a trie from its key,
1986          * but the search is either case sensitive or case
1987          * insensitive to the characters in the key, and this
1988          * choice of sensitivity or insensitivity is made when
1989          * the Trie is created, before any objects are put in it.
1990          *
1991          * This class is a copy of the one in com.sun.org.apache.xml.internal.utils.
1992          * It exists to cut the serializers dependancy on that package.
1993          *


< prev index next >