/* * reserved comment block * DO NOT REMOVE OR ALTER! */ /* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id: ToHTMLSAXHandler.java,v 1.3 2005/09/28 13:49:07 pvedula Exp $ */ package com.sun.org.apache.xml.internal.serializer; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import java.util.Properties; import javax.xml.transform.Result; import org.w3c.dom.Node; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.ext.LexicalHandler; /** * This class accepts SAX-like calls, then sends true SAX calls to a * wrapped SAX handler. There is optimization done knowing that the ultimate * output is HTML. * * This class is not a public API. * * @xsl.usage internal */ public final class ToHTMLSAXHandler extends ToSAXHandler { /** * Handle document type declaration (for first element only) */ private boolean m_dtdHandled = false; /** * Keeps track of whether output escaping is currently enabled */ protected boolean m_escapeSetting = true; /** * Returns null. * @return null * @see Serializer#getOutputFormat() */ public Properties getOutputFormat() { return null; } /** * Reurns null * @return null * @see Serializer#getOutputStream() */ public OutputStream getOutputStream() { return null; } /** * Returns null * @return null * @see Serializer#getWriter() */ public Writer getWriter() { return null; } /** * Does nothing. * */ public void indent(int n) throws SAXException { } /** * Does nothing. * @see DOMSerializer#serialize(Node) */ public void serialize(Node node) throws IOException { return; } /** * Turns special character escaping on/off. * * * @param escape true if escaping is to be set on. * * @see SerializationHandler#setEscaping(boolean) */ public boolean setEscaping(boolean escape) throws SAXException { boolean oldEscapeSetting = m_escapeSetting; m_escapeSetting = escape; if (escape) { processingInstruction(Result.PI_ENABLE_OUTPUT_ESCAPING, ""); } else { processingInstruction(Result.PI_DISABLE_OUTPUT_ESCAPING, ""); } return oldEscapeSetting; } /** * Does nothing * @param indent the number of spaces to indent per indentation level * (ignored) * @see SerializationHandler#setIndent(boolean) */ public void setIndent(boolean indent) { } /** * Does nothing. * @param format this parameter is not used * @see Serializer#setOutputFormat(Properties) */ public void setOutputFormat(Properties format) { } /** * Does nothing. * @param output this parameter is ignored * @see Serializer#setOutputStream(OutputStream) */ public void setOutputStream(OutputStream output) { } /** * Does nothing. * @param writer this parameter is ignored. * @see Serializer#setWriter(Writer) */ public void setWriter(Writer writer) { } /** * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String, String, String) */ /** * Does nothing. * * @param eName this parameter is ignored * @param aName this parameter is ignored * @param type this parameter is ignored * @param valueDefault this parameter is ignored * @param value this parameter is ignored * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String,String,String) */ public void attributeDecl( String eName, String aName, String type, String valueDefault, String value) throws SAXException { } /** * Does nothing. * @see org.xml.sax.ext.DeclHandler#elementDecl(String, String) */ public void elementDecl(String name, String model) throws SAXException { return; } /** * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(String, String, String) */ public void externalEntityDecl(String arg0, String arg1, String arg2) throws SAXException { } /** * Does nothing. * * @see org.xml.sax.DTDHandler#unparsedEntityDecl */ public void internalEntityDecl(String name, String value) throws SAXException { } /** * Receive notification of the end of an element. * *
The SAX parser will invoke this method at the end of every * element in the XML document; there will be a corresponding * startElement() event for every endElement() event (even when the * element is empty).
* *If the element name has a namespace prefix, the prefix will * still be attached to the name.
* * * @param uri The Namespace URI, or the empty string if the * element has no Namespace URI or if Namespace * processing is not being performed. * @param localName The local name (without prefix), or the * empty string if Namespace processing is not being * performed. * @param qName The qualified name (with prefix), or the * empty string if qualified names are not available. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * @see org.xml.sax.ContentHandler#endElement(String, String, String) */ public void endElement(String uri, String localName, String qName) throws SAXException { flushPending(); m_saxHandler.endElement(uri, localName, qName); // time to fire off endElement event if (m_tracer != null) super.fireEndElem(qName); } /** * Does nothing. */ public void endPrefixMapping(String prefix) throws SAXException { } /** * Does nothing. * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) */ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { } /** * Receive notification of a processing instruction. * *The Parser will invoke this method once for each processing * instruction found: note that processing instructions may occur * before or after the main document element.
* *A SAX parser should never report an XML declaration (XML 1.0, * section 2.8) or a text declaration (XML 1.0, section 4.3.1) * using this method.
* * @param target The processing instruction target. * @param data The processing instruction data, or null if * none was supplied. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * * @throws org.xml.sax.SAXException * @see org.xml.sax.ContentHandler#processingInstruction(String, String) */ public void processingInstruction(String target, String data) throws SAXException { flushPending(); m_saxHandler.processingInstruction(target,data); // time to fire off processing instruction event if (m_tracer != null) super.fireEscapingEvent(target,data); } /** * Does nothing. * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator) */ public void setDocumentLocator(Locator arg0) { super.setDocumentLocator(arg0); } /** * Does nothing. * @see org.xml.sax.ContentHandler#skippedEntity(String) */ public void skippedEntity(String arg0) throws SAXException { } /** * Receive notification of the beginning of an element, although this is a * SAX method additional namespace or attribute information can occur before * or after this call, that is associated with this element. * * * @param namespaceURI The Namespace URI, or the empty string if the * element has no Namespace URI or if Namespace * processing is not being performed. * @param localName The local name (without prefix), or the * empty string if Namespace processing is not being * performed. * @param qName The elements name. * @param atts The attributes attached to the element, if any. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * @see org.xml.sax.ContentHandler#startElement * @see org.xml.sax.ContentHandler#endElement * @see org.xml.sax.AttributeList * * @throws org.xml.sax.SAXException * * @see org.xml.sax.ContentHandler#startElement(String, String, String, Attributes) */ public void startElement( String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { flushPending(); super.startElement(namespaceURI, localName, qName, atts); m_saxHandler.startElement(namespaceURI, localName, qName, atts); m_elemContext.m_startTagOpen = false; } /** * Receive notification of a comment anywhere in the document. This callback * will be used for comments inside or outside the document element. * @param ch An array holding the characters in the comment. * @param start The starting position in the array. * @param length The number of characters to use from the array. * @throws org.xml.sax.SAXException The application may raise an exception. * * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int) */ public void comment(char[] ch, int start, int length) throws SAXException { flushPending(); if (m_lexHandler != null) m_lexHandler.comment(ch, start, length); // time to fire off comment event if (m_tracer != null) super.fireCommentEvent(ch, start, length); return; } /** * Does nothing. * @see org.xml.sax.ext.LexicalHandler#endCDATA() */ public void endCDATA() throws SAXException { return; } /** * Does nothing. * @see org.xml.sax.ext.LexicalHandler#endDTD() */ public void endDTD() throws SAXException { } /** * Does nothing. * @see org.xml.sax.ext.LexicalHandler#startCDATA() */ public void startCDATA() throws SAXException { } /** * Does nothing. * @see org.xml.sax.ext.LexicalHandler#startEntity(String) */ public void startEntity(String arg0) throws SAXException { } /** * Receive notification of the end of a document. * *The SAX parser will invoke this method only once, and it will * be the last method invoked during the parse. The parser shall * not invoke this method until it has either abandoned parsing * (because of an unrecoverable error) or reached the end of * input.
* * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * * @throws org.xml.sax.SAXException * * */ public void endDocument() throws SAXException { flushPending(); // Close output document m_saxHandler.endDocument(); if (m_tracer != null) super.fireEndDoc(); } /** * This method is called when all the data needed for a call to the * SAX handler's startElement() method has been gathered. */ protected void closeStartTag() throws SAXException { m_elemContext.m_startTagOpen = false; // Now is time to send the startElement event m_saxHandler.startElement( EMPTYSTRING, m_elemContext.m_elementName, m_elemContext.m_elementName, m_attributes); m_attributes.clear(); } /** * Do nothing. * @see SerializationHandler#close() */ public void close() { return; } /** * Receive notification of character data. * * @param chars The string of characters to process. * * @throws org.xml.sax.SAXException * * @see ExtendedContentHandler#characters(String) */ public void characters(final String chars) throws SAXException { final int length = chars.length(); if (length > m_charsBuff.length) { m_charsBuff = new char[length * 2 + 1]; } chars.getChars(0, length, m_charsBuff, 0); this.characters(m_charsBuff, 0, length); } /** * A constructor * @param handler the wrapped SAX content handler * @param encoding the encoding of the output HTML document */ public ToHTMLSAXHandler(ContentHandler handler, String encoding) { super(handler,encoding); } /** * A constructor. * @param handler the wrapped SAX content handler * @param lex the wrapped lexical handler * @param encoding the encoding of the output HTML document */ public ToHTMLSAXHandler( ContentHandler handler, LexicalHandler lex, String encoding) { super(handler,lex,encoding); } /** * An element starts, but attributes are not fully known yet. * * @param elementNamespaceURI the URI of the namespace of the element * (optional) * @param elementLocalName the element name, but without prefix * (optional) * @param elementName the element name, with prefix, if any (required) * * @see ExtendedContentHandler#startElement(String) */ public void startElement( String elementNamespaceURI, String elementLocalName, String elementName) throws SAXException { super.startElement(elementNamespaceURI, elementLocalName, elementName); flushPending(); // Handle document type declaration (for first element only) if (!m_dtdHandled) { String doctypeSystem = getDoctypeSystem(); String doctypePublic = getDoctypePublic(); if ((doctypeSystem != null) || (doctypePublic != null)) { if (m_lexHandler != null) m_lexHandler.startDTD( elementName, doctypePublic, doctypeSystem); } m_dtdHandled = true; } m_elemContext = m_elemContext.push(elementNamespaceURI, elementLocalName, elementName); } /** * An element starts, but attributes are not fully known yet. * * @param elementName the element name, with prefix, if any * * @see ExtendedContentHandler#startElement(String) */ public void startElement(String elementName) throws SAXException { this.startElement(null,null, elementName); } /** * Receive notification of the end of an element. * @param elementName The element type name * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * * @see ExtendedContentHandler#endElement(String) */ public void endElement(String elementName) throws SAXException { flushPending(); m_saxHandler.endElement(EMPTYSTRING, elementName, elementName); // time to fire off endElement event if (m_tracer != null) super.fireEndElem(elementName); } /** * Receive notification of character data. * *The Parser will call this method to report each chunk of * character data. SAX parsers may return all contiguous character * data in a single chunk, or they may split it into several * chunks; however, all of the characters in any single event * must come from the same external entity, so that the Locator * provides useful information.
* *The application must not attempt to read from the array * outside of the specified range.
* *Note that some parsers will report whitespace using the * ignorableWhitespace() method rather than this one (validating * parsers must do so).
* * @param ch The characters from the XML document. * @param off The start position in the array. * @param len The number of characters to read from the array. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * @see #ignorableWhitespace * @see org.xml.sax.Locator * * @throws org.xml.sax.SAXException * * @see org.xml.sax.ContentHandler#characters(char[], int, int) */ public void characters(char[] ch, int off, int len) throws SAXException { flushPending(); m_saxHandler.characters(ch, off, len); // time to fire off characters event if (m_tracer != null) super.fireCharEvent(ch, off, len); } /** * This method flushes any pending events, which can be startDocument() * closing the opening tag of an element, or closing an open CDATA section. */ public void flushPending() throws SAXException { if (m_needToCallStartDocument) { startDocumentInternal(); m_needToCallStartDocument = false; } // Close any open element if (m_elemContext.m_startTagOpen) { closeStartTag(); m_elemContext.m_startTagOpen = false; } } /** * Handle a prefix/uri mapping, which is associated with a startElement() * that is soon to follow. Need to close any open start tag to make * sure than any name space attributes due to this event are associated wih * the up comming element, not the current one. * @see ExtendedContentHandler#startPrefixMapping * * @param prefix The Namespace prefix being declared. * @param uri The Namespace URI the prefix is mapped to. * @param shouldFlush true if any open tags need to be closed first, this * will impact which element the mapping applies to (open parent, or its up * comming child) * @return returns true if the call made a change to the current * namespace information, false if it did not change anything, e.g. if the * prefix/namespace mapping was already in scope from before. * * @throws org.xml.sax.SAXException The client may throw * an exception during processing. */ public boolean startPrefixMapping( String prefix, String uri, boolean shouldFlush) throws SAXException { // no namespace support for HTML if (shouldFlush) flushPending(); m_saxHandler.startPrefixMapping(prefix,uri); return false; } /** * Begin the scope of a prefix-URI Namespace mapping * just before another element is about to start. * This call will close any open tags so that the prefix mapping * will not apply to the current element, but the up comming child. * * @see org.xml.sax.ContentHandler#startPrefixMapping * * @param prefix The Namespace prefix being declared. * @param uri The Namespace URI the prefix is mapped to. * * @throws org.xml.sax.SAXException The client may throw * an exception during processing. * */ public void startPrefixMapping(String prefix, String uri) throws org.xml.sax.SAXException { startPrefixMapping(prefix,uri,true); } /** * This method is used when a prefix/uri namespace mapping * is indicated after the element was started with a * startElement() and before and endElement(). * startPrefixMapping(prefix,uri) would be used before the * startElement() call. * @param prefix the prefix associated with the given URI. * @param uri the URI of the namespace * * @see ExtendedContentHandler#namespaceAfterStartElement(String, String) */ public void namespaceAfterStartElement( final String prefix, final String uri) throws SAXException { // hack for XSLTC with finding URI for default namespace if (m_elemContext.m_elementURI == null) { String prefix1 = getPrefixPart(m_elemContext.m_elementName); if (prefix1 == null && EMPTYSTRING.equals(prefix)) { // the elements URI is not known yet, and it // doesn't have a prefix, and we are currently // setting the uri for prefix "", so we have // the uri for the element... lets remember it m_elemContext.m_elementURI = uri; } } startPrefixMapping(prefix,uri,false); } /** * Try's to reset the super class and reset this class for * re-use, so that you don't need to create a new serializer * (mostly for performance reasons). * * @return true if the class was successfuly reset. * @see Serializer#reset() */ public boolean reset() { boolean wasReset = false; if (super.reset()) { resetToHTMLSAXHandler(); wasReset = true; } return wasReset; } /** * Reset all of the fields owned by ToHTMLSAXHandler class * */ private void resetToHTMLSAXHandler() { this.m_escapeSetting = true; } }