| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 2001-2003 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xalan" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF |
| * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2001, Sun |
| * Microsystems., http://www.sun.com. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| * @author Santiago Pericas-Geertsen |
| * @author G. Todd Miller |
| * |
| */ |
| package org.apache.xml.serializer; |
| |
| import java.util.Vector; |
| |
| import org.xml.sax.Attributes; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| import org.xml.sax.ext.LexicalHandler; |
| |
| abstract public class ToSAXHandler extends SerializerBase |
| { |
| public ToSAXHandler() |
| { |
| } |
| |
| public ToSAXHandler( |
| ContentHandler hdlr, |
| LexicalHandler lex, |
| String encoding) |
| { |
| setContentHandler(hdlr); |
| setLexHandler(lex); |
| setEncoding(encoding); |
| } |
| public ToSAXHandler(ContentHandler handler, String encoding) |
| { |
| setContentHandler(handler); |
| setEncoding(encoding); |
| } |
| |
| /** |
| * Underlying SAX handler. Taken from XSLTC |
| */ |
| protected ContentHandler m_saxHandler; |
| |
| /** |
| * Underlying LexicalHandler. Taken from XSLTC |
| */ |
| protected LexicalHandler m_lexHandler; |
| |
| /** |
| * A startPrefixMapping() call on a ToSAXHandler will pass that call |
| * on to the wrapped ContentHandler, but should we also mirror these calls |
| * with matching attributes, if so this field is true. |
| * For example if this field is true then a call such as |
| * startPrefixMapping("prefix1","uri1") will also cause the additional |
| * internally generated attribute xmlns:prefix1="uri1" to be effectively added |
| * to the attributes passed to the wrapped ContentHandler. |
| */ |
| private boolean m_shouldGenerateNSAttribute = true; |
| |
| /** If this is true, then the content handler wrapped by this |
| * serializer implements the TransformState interface which |
| * will give the content handler access to the state of |
| * the transform. */ |
| protected TransformStateSetter m_state = null; |
| |
| /** |
| * Pass callback to the SAX Handler |
| */ |
| protected void startDocumentInternal() throws SAXException |
| { |
| if (m_needToCallStartDocument) |
| { |
| super.startDocumentInternal(); |
| |
| m_saxHandler.startDocument(); |
| m_needToCallStartDocument = false; |
| } |
| } |
| /** |
| * Do nothing. |
| * @see org.xml.sax.ext.LexicalHandler#startDTD(String, String, String) |
| */ |
| public void startDTD(String arg0, String arg1, String arg2) |
| throws SAXException |
| { |
| // do nothing for now |
| } |
| |
| /** |
| * Receive notification of character data. |
| * |
| * @param chars The string of characters to process. |
| * |
| * @throws org.xml.sax.SAXException |
| * |
| * @see org.apache.xml.serializer.ExtendedContentHandler#characters(String) |
| */ |
| public void characters(String characters) throws SAXException |
| { |
| final int len = characters.length(); |
| if (len > m_charsBuff.length) |
| { |
| m_charsBuff = new char[len*2 + 1]; |
| } |
| characters.getChars(0,len, m_charsBuff, 0); |
| characters(m_charsBuff, 0, len); |
| } |
| |
| /** |
| * Receive notification of a comment. |
| * |
| * @see org.apache.xml.serializer.ExtendedLexicalHandler#comment(String) |
| */ |
| public void comment(String comment) throws SAXException |
| { |
| |
| // Close any open element before emitting comment |
| if (m_elemContext.m_startTagOpen) |
| { |
| closeStartTag(); |
| } |
| else if (m_cdataTagOpen) |
| { |
| closeCDATA(); |
| } |
| |
| // Ignore if a lexical handler has not been set |
| if (m_lexHandler != null) |
| { |
| final int len = comment.length(); |
| if (len > m_charsBuff.length) |
| { |
| m_charsBuff = new char[len*2 + 1]; |
| } |
| comment.getChars(0,len, m_charsBuff, 0); |
| m_lexHandler.comment(m_charsBuff, 0, len); |
| // time to fire off comment event |
| if (m_tracer != null) |
| super.fireCommentEvent(m_charsBuff, 0, len); |
| } |
| |
| } |
| |
| /** |
| * Do nothing as this is an abstract class. All subclasses will need to |
| * define their behavior if it is different. |
| * @see org.xml.sax.ContentHandler#processingInstruction(String, String) |
| */ |
| public void processingInstruction(String target, String data) |
| throws SAXException |
| { |
| // Redefined in SAXXMLOutput |
| } |
| |
| protected void closeStartTag() throws SAXException |
| { |
| } |
| |
| protected void closeCDATA() throws SAXException |
| { |
| // Redefined in SAXXMLOutput |
| } |
| |
| /** |
| * 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 name The element type 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 arg0, |
| String arg1, |
| String arg2, |
| Attributes arg3) |
| throws SAXException |
| { |
| if (m_state != null) { |
| m_state.resetState(getTransformer()); |
| } |
| |
| // fire off the start element event |
| if (m_tracer != null) |
| super.fireStartElem(arg2); |
| } |
| |
| /** |
| * Sets the LexicalHandler. |
| * @param _lexHandler The LexicalHandler to set |
| */ |
| public void setLexHandler(LexicalHandler _lexHandler) |
| { |
| this.m_lexHandler = _lexHandler; |
| } |
| |
| /** |
| * Sets the SAX ContentHandler. |
| * @param m_saxHandler The ContentHandler to set |
| */ |
| public void setContentHandler(ContentHandler _saxHandler) |
| { |
| this.m_saxHandler = _saxHandler; |
| if (m_lexHandler == null && _saxHandler instanceof LexicalHandler) |
| { |
| // we are not overwriting an existing LexicalHandler, and _saxHandler |
| // is also implements LexicalHandler, so lets use it |
| m_lexHandler = (LexicalHandler) _saxHandler; |
| } |
| } |
| |
| /** |
| * Does nothing. The setting of CDATA section elements has an impact on |
| * stream serializers. |
| * @see org.apache.xml.serializer.SerializationHandler#setCdataSectionElements(java.util.Vector) |
| */ |
| public void setCdataSectionElements(Vector URI_and_localNames) |
| { |
| // do nothing |
| } |
| |
| /** Set whether or not namespace declarations (e.g. |
| * xmlns:foo) should appear as attributes of |
| * elements |
| * @param doOutputNSAttr whether or not namespace declarations |
| * should appear as attributes |
| */ |
| public void setShouldOutputNSAttr(boolean doOutputNSAttr) |
| { |
| m_shouldGenerateNSAttribute = doOutputNSAttr; |
| } |
| |
| /** |
| * Returns true if namespace declarations from calls such as |
| * startPrefixMapping("prefix1","uri1") should |
| * also be mirrored with self generated additional attributes of elements |
| * that declare the namespace, for example the attribute xmlns:prefix1="uri1" |
| */ |
| boolean getShouldOutputNSAttr() |
| { |
| return m_shouldGenerateNSAttribute; |
| } |
| |
| /** |
| * 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; |
| } |
| |
| if (m_elemContext.m_startTagOpen) |
| { |
| closeStartTag(); |
| m_elemContext.m_startTagOpen = false; |
| } |
| |
| if (m_cdataTagOpen) |
| { |
| closeCDATA(); |
| m_cdataTagOpen = false; |
| } |
| |
| } |
| |
| /** |
| * Pass in a reference to a TransformState object, which |
| * can be used during SAX ContentHandler events to obtain |
| * information about he state of the transformation. This |
| * method will be called before each startDocument event. |
| * |
| * @param ts A reference to a TransformState object |
| */ |
| public void setTransformState(TransformStateSetter ts) { |
| this.m_state = ts; |
| } |
| |
| /** |
| * Receives notification that an element starts, but attributes are not |
| * fully known yet. |
| * |
| * @param uri the URI of the namespace of the element (optional) |
| * @param localName the element name, but without prefix (optional) |
| * @param qName the element name, with prefix, if any (required) |
| * |
| * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(String, String, String) |
| */ |
| public void startElement(String uri, String localName, String qName) |
| throws SAXException { |
| |
| if (m_state != null) { |
| m_state.resetState(getTransformer()); |
| } |
| |
| // fire off the start element event |
| if (m_tracer != null) |
| super.fireStartElem(qName); |
| } |
| |
| /** |
| * An element starts, but attributes are not fully known yet. |
| * |
| * @param elementName the element name, with prefix (if any). |
| |
| * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(String) |
| */ |
| public void startElement(String qName) throws SAXException { |
| if (m_state != null) { |
| m_state.resetState(getTransformer()); |
| } |
| // fire off the start element event |
| if (m_tracer != null) |
| super.fireStartElem(qName); |
| } |
| |
| /** |
| * This method gets the node's value as a String and uses that String as if |
| * it were an input character notification. |
| * @param node the Node to serialize |
| * @throws org.xml.sax.SAXException |
| */ |
| public void characters(org.w3c.dom.Node node) |
| throws org.xml.sax.SAXException |
| { |
| // remember the current node |
| if (m_state != null) |
| { |
| m_state.setCurrentNode(node); |
| } |
| |
| // Get the node's value as a String and use that String as if |
| // it were an input character notification. |
| String data = node.getNodeValue(); |
| if (data != null) { |
| this.characters(data); |
| } |
| } |
| |
| /** |
| * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException) |
| */ |
| public void fatalError(SAXParseException exc) throws SAXException { |
| super.fatalError(exc); |
| |
| m_needToCallStartDocument = false; |
| |
| if (m_saxHandler instanceof ErrorHandler) { |
| ((ErrorHandler)m_saxHandler).fatalError(exc); |
| } |
| } |
| |
| /** |
| * @see org.xml.sax.ErrorHandler#error(SAXParseException) |
| */ |
| public void error(SAXParseException exc) throws SAXException { |
| super.error(exc); |
| |
| if (m_saxHandler instanceof ErrorHandler) |
| ((ErrorHandler)m_saxHandler).error(exc); |
| |
| } |
| |
| /** |
| * @see org.xml.sax.ErrorHandler#warning(SAXParseException) |
| */ |
| public void warning(SAXParseException exc) throws SAXException { |
| super.warning(exc); |
| |
| if (m_saxHandler instanceof ErrorHandler) |
| ((ErrorHandler)m_saxHandler).warning(exc); |
| } |
| |
| |
| /** |
| * 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 org.apache.xml.serializer.Serializer#reset() |
| */ |
| public boolean reset() |
| { |
| boolean wasReset = false; |
| if (super.reset()) |
| { |
| resetToSAXHandler(); |
| wasReset = true; |
| } |
| return wasReset; |
| } |
| |
| /** |
| * Reset all of the fields owned by ToSAXHandler class |
| * |
| */ |
| private void resetToSAXHandler() |
| { |
| this.m_lexHandler = null; |
| this.m_saxHandler = null; |
| this.m_state = null; |
| this.m_shouldGenerateNSAttribute = false; |
| } |
| |
| /** |
| * Add a unique attribute |
| */ |
| public void addUniqueAttribute(String qName, String value, int flags) |
| throws SAXException |
| { |
| addAttribute(qName, value); |
| } |
| } |