minchau     2003/06/03 15:27:26

  Modified:    java/src/org/apache/xml/serializer ToHTMLStream.java
  Log:
  Optimization to ToHTMLStream.startElement() and endElement() to not save and restore
  so much information for empty elements, i.e. elements with no children such as the 
<IMG> tag.
  The endElement() should immediately follow the startElement().
  
  But even if such an element has an unexpected child the code will still
  work as before.
  
  Submitted by: Brian Minchau
  
  Revision  Changes    Path
  1.12      +171 -172  xml-xalan/java/src/org/apache/xml/serializer/ToHTMLStream.java
  
  Index: ToHTMLStream.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToHTMLStream.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- ToHTMLStream.java 31 May 2003 17:40:19 -0000      1.11
  +++ ToHTMLStream.java 3 Jun 2003 22:27:26 -0000       1.12
  @@ -716,9 +716,14 @@
           Attributes atts)
           throws org.xml.sax.SAXException
       {
  -        // System.out.println("SerializerToHTML#startElement("+namespaceURI+", 
"+localName+", "+name+", ...);");
   
  -        if (m_cdataTagOpen)
  +        // clean up any pending things first
  +        if (m_startTagOpen)
  +        {
  +            closeStartTag();
  +            m_startTagOpen = false;
  +        }
  +        else if (m_cdataTagOpen)
           {
               closeCDATA();
               m_cdataTagOpen = false;
  @@ -728,103 +733,92 @@
               startDocumentInternal();
               m_needToCallStartDocument = false;
           }
  -            
  -//        if (m_needToOutputDocTypeDecl 
  -//        && ( (null != getDoctypeSystem()) || (null!= getDoctypePublic())))
  -//        {
  -//            outputDocTypeDecl(name, true);
  -//        }
  -//        m_needToOutputDocTypeDecl = false;
   
   
  +        // if this element has a namespace then treat it like XML
           if (null != namespaceURI && namespaceURI.length() > 0)
           {
               super.startElement(namespaceURI, localName, name, atts);
   
               return;
           }
  -
  -        try
  -        {
  -        boolean savedDoIndent = m_doIndent;
  -        boolean noLineBreak;
  -        if (m_startTagOpen)
  -        {
  -            closeStartTag();
  -            m_startTagOpen = false;
  -        }
  -
  -        ElemDesc elemDesc = getElemDesc(name);
  - 
           
  -        // ElemDesc parentElemDesc = getElemDesc(m_currentElementName);
  -        boolean isBlockElement = elemDesc.is(ElemDesc.BLOCK);
  -        boolean isHeadElement = elemDesc.is(ElemDesc.HEADELEM);
  -
  -        // boolean isWhiteSpaceSensitive = 
elemDesc.is(ElemDesc.WHITESPACESENSITIVE);
  -        if (m_ispreserve)
  -            m_ispreserve = false;
  -        else if (
  -            m_doIndent
  -            && (null != m_elementName)
  -            && (!m_inBlockElem || isBlockElement) /* && !isWhiteSpaceSensitive */
  -            )
  +        try
           {
  -            m_startNewLine = true;
  -
  -            indent();
  -        }
  -
  -        m_inBlockElem = !isBlockElement;
  -        
  -        // remember for later
  -         m_elementLocalName = localName;
  -         m_elementURI = namespaceURI;
  -         m_elementName = name;
  -         m_elementDesc = elemDesc;        
  -
  -        m_isRawStack.push(elemDesc.is(ElemDesc.RAW));
  +            ElemDesc elemDesc = getElemDesc(name);
  +            // deal with indentation issues first
  +            if (m_doIndent)
  +            {
   
  -        // m_parents.push(m_currentElementName);
  -        m_writer.write('<');
  -        m_writer.write(name);
  +                boolean isBlockElement = elemDesc.is(ElemDesc.BLOCK);
  +                isBlockElement = elemDesc.is(ElemDesc.BLOCK);
  +                if (m_ispreserve)
  +                    m_ispreserve = false;
  +                else if (
  +                    (null != m_elementName)
  +                    && (!m_inBlockElem
  +                        || isBlockElement) /* && !isWhiteSpaceSensitive */
  +                    )
  +                {
  +                    m_startNewLine = true;
   
  -        if (atts != null)
  -            addAttributes(atts);
  +                    indent();
   
  -        // mark that the closing '>' of the starting tag is not yet written out
  -        m_startTagOpen = true;
  -        m_currentElemDepth++; // current element is one element deeper
  -        m_isprevtext = false;
  -        m_doIndent = savedDoIndent;
  +                }
  +                m_inBlockElem = !isBlockElement;
  +            }
   
  -        if (isHeadElement)
  -        {
  -            if (m_startTagOpen)
  +            // save any attributes for later processing
  +            if (atts != null)
  +                addAttributes(atts);            
  +
  +            // deal with the opening tag itself
  +            m_startTagOpen = true;
  +            m_elementDesc = elemDesc;
  +            m_isprevtext = false;
  +            m_writer.write('<');
  +            m_writer.write(name);
  +            
  +            
  +            // OPTIMIZE-EMPTY 
  +            if (elemDesc.is(ElemDesc.EMPTY))
               {
  -                closeStartTag();
  -                m_startTagOpen = false;
  +                // if the element is empty (has no children) then we can quit early 
and
  +                // not update all the other state information because the 
endElement() is
  +                // coming right away.  If you want to kill this optimization the 
corresponding
  +                // optimization "OPTIMIZE-EMPTY in endElement() must be killed too.
  +                return;
               }
   
  -            if (!m_omitMetaTag)
  +            // update any state information
  +            m_elementLocalName = localName;
  +            m_elementURI = namespaceURI;
  +            m_elementName = name;
  +            m_isRawStack.push(elemDesc.is(ElemDesc.RAW));
  +            m_currentElemDepth++; // current element is one element deeper
  +            
  +            if (elemDesc.is(ElemDesc.HEADELEM))
               {
  -                if (m_doIndent)
  -                    indent();
  -
  -                m_writer.write("<META http-equiv=\"Content-Type\" 
content=\"text/html; charset=");
  -
  -                // String encoding = 
Encodings.getMimeEncoding(m_encoding).toLowerCase();
  -                String encoding = getEncoding();
  -                String encode = Encodings.getMimeEncoding(encoding);
  -
  -                m_writer.write(encode);
  -                //m_writer.write('"');
  -                //m_writer.write('>');
  -                m_writer.write("\">");
  +                // This is the <HEAD> element, do some special processing
  +                if (m_startTagOpen)
  +                {
  +                    closeStartTag();
  +                    m_startTagOpen = false;
  +                }
  +                if (!m_omitMetaTag)
  +                {
  +                    if (m_doIndent)
  +                        indent();
  +                    m_writer.write(
  +                        "<META http-equiv=\"Content-Type\" content=\"text/html; 
charset=");
  +                    String encoding = getEncoding();
  +                    String encode = Encodings.getMimeEncoding(encoding);
  +                    m_writer.write(encode);
  +                    m_writer.write("\">");
  +                }
               }
           }
  -        }
  -        catch(IOException e)
  +        catch (IOException e)
           {
               throw new SAXException(e);
           }
  @@ -841,16 +835,16 @@
        *             wrapping another exception.
        */
       public final void endElement(
  -        String namespaceURI,
  -        String localName,
  -        String name)
  +        final String namespaceURI,
  +        final String localName,
  +        final String name)
           throws org.xml.sax.SAXException
       {
  -        // System.out.println("SerializerToHTML#endElement("+namespaceURI+", 
"+localName+", "+name+");");
  -
  +        // deal with any pending issues
           if (m_cdataTagOpen)
               closeCDATA();
   
  +        // if the element has a namespace, treat it like XML, not HTML
           if (null != namespaceURI && namespaceURI.length() > 0)
           {
               super.endElement(namespaceURI, localName, name);
  @@ -858,113 +852,118 @@
               return;
           }
   
  -        m_currentElemDepth--;
  -
  -        // System.out.println(m_currentElementName);
  -        // m_parents.pop();
  -        m_isRawStack.pop();
  -
  -        ElemDesc elemDesc = getElemDesc(name);
  -        m_elementDesc = elemDesc;
  -
  -        // ElemDesc parentElemDesc = getElemDesc(m_currentElementName);
  -        boolean isBlockElement = elemDesc.is(ElemDesc.BLOCK);
  -        boolean shouldIndent = false;
  -
  -        if (m_ispreserve)
  -        {
  -            m_ispreserve = false;
  -        }
  -        else if (m_doIndent && (!m_inBlockElem || isBlockElement))
  -        {
  -            m_startNewLine = true;
  -            shouldIndent = true;
  -
  -            // indent(m_currentIndent);
  -        }
  -
  -        m_inBlockElem = !isBlockElement;
  -
           try
           {
  -        if (!m_startTagOpen)
  -        {
  -            // this block is like a copy of closeStartTag()
  -            // except that 
  -            if (shouldIndent)
  -                indent();
   
  -            m_writer.write("</");
  -            m_writer.write(name);
  -            m_writer.write('>');
  +            final ElemDesc elemDesc = getElemDesc(name);
  +            m_elementDesc = elemDesc;
  +            final boolean elemEmpty = elemDesc.is(ElemDesc.EMPTY);
   
  -            m_elementName = name;
  +            // deal with any indentation issues
  +            if (m_doIndent)
  +            {
  +                boolean isBlockElement = elemDesc.is(ElemDesc.BLOCK);
  +                boolean shouldIndent = false;
   
  -            if (m_cdataSectionElements != null)
  -                m_cdataSectionStates.pop();
  -            if (m_doIndent && !m_preserves.isEmpty())
  -                m_preserves.pop();
  -        }
  -        else
  -        {
  -            if (m_tracer != null)
  -                super.fireStartElem(m_elementName);
  -            /* process any attributes gathered after the
  -             * startElement(String) call
  -             */
  -            int nAttrs = m_attributes.getLength();
  -            if (nAttrs > 0)
  -                processAttributes(nAttrs);
  -            if (!elemDesc.is(ElemDesc.EMPTY))
  -            {
  -
  -                // As per Dave/Paul recommendation 12/06/2000
  -                // if (shouldIndent)
  -                // m_writer.write('>');
  -                //  indent(m_currentIndent);
  +                if (m_ispreserve)
  +                {
  +                    m_ispreserve = false;
  +                }
  +                else if (m_doIndent && (!m_inBlockElem || isBlockElement))
  +                {
  +                    m_startNewLine = true;
  +                    shouldIndent = true;
  +                }
  +                if (!m_startTagOpen && shouldIndent)
  +                    indent();
  +                m_inBlockElem = !isBlockElement;
  +            }
   
  -                m_writer.write("></");
  +            if (!m_startTagOpen)
  +            {
  +                m_writer.write("</");
                   m_writer.write(name);
                   m_writer.write('>');
               }
               else
               {
  -                m_writer.write('>');
  -            }
  -
  -            /* no need to call m_cdataSectionStates.pop();
  -             * because pushCdataSectionState() was never called
  -             * ... the endElement call came before we had a chance
  -             * to push the state.
  -             */
  +                // the start-tag was already closed.
  +                
  +                if (m_tracer != null)
  +                    super.fireStartElem(m_elementName);
  +
  +                // the starting tag was still open when we received this 
endElement() call
  +                // so we need to process any gathered attributes NOW, before they 
go away.
  +                int nAttrs = m_attributes.getLength();
  +                if (nAttrs > 0)
  +                    processAttributes(nAttrs);
  +                if (!elemEmpty)
  +                {
  +                    // As per Dave/Paul recommendation 12/06/2000
  +                    // if (shouldIndent)
  +                    // m_writer.write('>');
  +                    //  indent(m_currentIndent);
  +
  +                    m_writer.write("></");
  +                    m_writer.write(name);
  +                    m_writer.write('>');
  +                }
  +                else
  +                {
  +                    m_writer.write('>');
  +                }
  +
  +                /* no need to call m_cdataSectionStates.pop();
  +                 * because pushCdataSectionState() was never called
  +                 * ... the endElement call came before we had a chance
  +                 * to push the state.
  +                 */
   
  -        }
  +            }
  +            
  +            // clean up because the element has ended
  +            if (elemDesc.is(ElemDesc.WHITESPACESENSITIVE))
  +                m_ispreserve = true;
  +            m_isprevtext = false;
  +            m_elementURI = null;
  +            m_elementLocalName = null;
   
  -        if (elemDesc.is(ElemDesc.WHITESPACESENSITIVE))
  -            m_ispreserve = true;
  +            // fire off the end element event
  +            if (m_tracer != null)
  +                super.fireEndElem(name);            
  +                           
  +            // OPTIMIZE-EMPTY                
  +            if (elemEmpty)
  +            {
  +                // a quick exit if the HTML element had no children.
  +                // This block of code can be removed if the corresponding block of 
code
  +                // in startElement() also labeled with "OPTIMIZE-EMPTY" is also 
removed
  +                m_startTagOpen = false;
  +                return;
  +            }
   
  -        /* we don't have any open tags anymore, since we just 
  -         * wrote out a closing ">" 
  -         */
  -        m_startTagOpen = false;
  +            // some more clean because the element has ended. 
  +            if (!m_startTagOpen)
  +            {
  +                if (m_cdataSectionElements != null)
  +                    m_cdataSectionStates.pop();
  +                if (m_doIndent && !m_preserves.isEmpty())
  +                    m_preserves.pop();
  +            }
  +            else
  +                m_startTagOpen = false;
  +            /* At this point m_startTagOpen is always false because
  +             * we don't have any open tags anymore, since we just 
  +             * wrote out a closing ">" 
  +             */ 
   
  -        m_isprevtext = false;
  -        
  +            m_currentElemDepth--;
  +            m_isRawStack.pop();
           }
  -        catch(IOException e)
  +        catch (IOException e)
           {
               throw new SAXException(e);
           }
  -        
  -
  -        m_elementURI = null;
  -        m_elementLocalName = null;
  -
  -        // fire off the end element event
  -
  -        if (m_tracer != null)
  -            super.fireEndElem(name);        
  - 
       }
   
       /**
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to