< 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();


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.


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

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


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

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


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

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


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

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


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


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


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

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


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


1954             throws SAXException
1955     {
1956         // The internal DTD subset is not serialized by the ToHTMLStream serializer
1957         if (m_inDTD)
1958             return;
1959         super.comment(ch, start, length);
1960     }
1961 
1962     public boolean reset()
1963     {
1964         boolean ret = super.reset();
1965         if (!ret)
1966             return false;
1967         initToHTMLStream();
1968         return true;
1969     }
1970 
1971     private void initToHTMLStream()
1972     {
1973 //        m_elementDesc = null;
1974         m_isprevblock = false;
1975         m_inDTD = false;
1976 //        m_isRawStack.clear();
1977         m_omitMetaTag = false;
1978         m_specialEscapeURLs = true;
1979     }
1980 
1981     static class Trie
1982     {
1983         /**
1984          * A digital search trie for 7-bit ASCII text
1985          * The API is a subset of java.util.Hashtable
1986          * The key must be a 7-bit ASCII string
1987          * The value may be any Java Object
1988          * One can get an object stored in a trie from its key,
1989          * but the search is either case sensitive or case
1990          * insensitive to the characters in the key, and this
1991          * choice of sensitivity or insensitivity is made when
1992          * the Trie is created, before any objects are put in it.
1993          *
1994          * This class is a copy of the one in com.sun.org.apache.xml.internal.utils.


< prev index next >