/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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: TransformerHandlerImpl.java 468645 2006-10-28 06:57:24Z minchau $ */ package org.apache.xalan.transformer; import java.io.IOException; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.sax.TransformerHandler; import org.apache.xalan.res.XSLMessages; import org.apache.xalan.res.XSLTErrorResources; import org.apache.xml.dtm.DTM; import org.apache.xml.dtm.DTMManager; import org.apache.xml.dtm.ref.IncrementalSAXSource_Filter; import org.apache.xml.dtm.ref.sax2dtm.SAX2DTM; import org.apache.xpath.XPathContext; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.ext.DeclHandler; import org.xml.sax.ext.LexicalHandler; import org.apache.xml.serializer.SerializationHandler; /** * A TransformerHandler * listens for SAX ContentHandler parse events and transforms * them to a Result. */ public class TransformerHandlerImpl implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler, LexicalHandler, TransformerHandler, DeclHandler { /** * The flag for the setting of the optimize feature; */ private final boolean m_optimizer; /** * The flag for the setting of the incremental feature; */ private final boolean m_incremental; /** * The flag for the setting of the source_location feature; */ private final boolean m_source_location; private boolean m_insideParse = false; //////////////////////////////////////////////////////////////////// // Constructors. //////////////////////////////////////////////////////////////////// /** * Construct a TransformerHandlerImpl. * * @param transformer Non-null reference to the Xalan transformer impl. * @param doFragment True if the result should be a document fragement. * @param baseSystemID The system ID to use as the base for relative URLs. */ public TransformerHandlerImpl(TransformerImpl transformer, boolean doFragment, String baseSystemID) { super(); m_transformer = transformer; m_baseSystemID = baseSystemID; XPathContext xctxt = transformer.getXPathContext(); DTM dtm = xctxt.getDTM(null, true, transformer, true, true); m_dtm = dtm; dtm.setDocumentBaseURI(baseSystemID); m_contentHandler = dtm.getContentHandler(); m_dtdHandler = dtm.getDTDHandler(); m_entityResolver = dtm.getEntityResolver(); m_errorHandler = dtm.getErrorHandler(); m_lexicalHandler = dtm.getLexicalHandler(); m_incremental = transformer.getIncremental(); m_optimizer = transformer.getOptimize(); m_source_location = transformer.getSource_location(); } /** * Do what needs to be done to shut down the CoRoutine management. */ protected void clearCoRoutine() { clearCoRoutine(null); } /** * Do what needs to be done to shut down the CoRoutine management. */ protected void clearCoRoutine(SAXException ex) { if(null != ex) m_transformer.setExceptionThrown(ex); if(m_dtm instanceof SAX2DTM) { if(DEBUG) System.err.println("In clearCoRoutine..."); try { SAX2DTM sax2dtm = ((SAX2DTM)m_dtm); if(null != m_contentHandler && m_contentHandler instanceof IncrementalSAXSource_Filter) { IncrementalSAXSource_Filter sp = (IncrementalSAXSource_Filter)m_contentHandler; // This should now be all that's needed. sp.deliverMoreNodes(false); } sax2dtm.clearCoRoutine(true); m_contentHandler = null; m_dtdHandler = null; m_entityResolver = null; m_errorHandler = null; m_lexicalHandler = null; } catch(Throwable throwable) { throwable.printStackTrace(); } if(DEBUG) System.err.println("...exiting clearCoRoutine"); } } //////////////////////////////////////////////////////////////////// // Implementation of javax.xml.transform.sax.TransformerHandler. //////////////////////////////////////////////////////////////////// /** * Enables the user of the TransformerHandler to set the * to set the Result for the transformation. * * @param result A Result instance, should not be null. * * @throws IllegalArgumentException if result is invalid for some reason. */ public void setResult(Result result) throws IllegalArgumentException { if (null == result) throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_RESULT_NULL, null)); //"result should not be null"); try { // ContentHandler handler = // m_transformer.createResultContentHandler(result); // m_transformer.setContentHandler(handler); SerializationHandler xoh = m_transformer.createSerializationHandler(result); m_transformer.setSerializationHandler(xoh); } catch (javax.xml.transform.TransformerException te) { throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_RESULT_COULD_NOT_BE_SET, null)); //"result could not be set"); } m_result = result; } /** * Set the base ID (URI or system ID) from where relative * URLs will be resolved. * @param systemID Base URI for the source tree. */ public void setSystemId(String systemID) { m_baseSystemID = systemID; m_dtm.setDocumentBaseURI(systemID); } /** * Get the base ID (URI or system ID) from where relative * URLs will be resolved. * @return The systemID that was set with {@link #setSystemId}. */ public String getSystemId() { return m_baseSystemID; } /** * Get the Transformer associated with this handler, which * is needed in order to set parameters and output properties. * * @return The Transformer associated with this handler */ public Transformer getTransformer() { return m_transformer; } //////////////////////////////////////////////////////////////////// // Implementation of org.xml.sax.EntityResolver. //////////////////////////////////////////////////////////////////// /** * Filter an external entity resolution. * * @param publicId The entity's public identifier, or null. * @param systemId The entity's system identifier. * @return A new InputSource or null for the default. * * @throws IOException * @throws SAXException The client may throw * an exception during processing. * @throws java.io.IOException The client may throw an * I/O-related exception while obtaining the * new InputSource. * @see org.xml.sax.EntityResolver#resolveEntity */ public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if (m_entityResolver != null) { return m_entityResolver.resolveEntity(publicId, systemId); } else { return null; } } //////////////////////////////////////////////////////////////////// // Implementation of org.xml.sax.DTDHandler. //////////////////////////////////////////////////////////////////// /** * Filter a notation declaration event. * * @param name The notation name. * @param publicId The notation's public identifier, or null. * @param systemId The notation's system identifier, or null. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.DTDHandler#notationDecl */ public void notationDecl(String name, String publicId, String systemId) throws SAXException { if (m_dtdHandler != null) { m_dtdHandler.notationDecl(name, publicId, systemId); } } /** * Filter an unparsed entity declaration event. * * @param name The entity name. * @param publicId The entity's public identifier, or null. * @param systemId The entity's system identifier, or null. * @param notationName The name of the associated notation. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.DTDHandler#unparsedEntityDecl */ public void unparsedEntityDecl( String name, String publicId, String systemId, String notationName) throws SAXException { if (m_dtdHandler != null) { m_dtdHandler.unparsedEntityDecl(name, publicId, systemId, notationName); } } //////////////////////////////////////////////////////////////////// // Implementation of org.xml.sax.ContentHandler. //////////////////////////////////////////////////////////////////// /** * Filter a new document locator event. * * @param locator The document locator. * @see org.xml.sax.ContentHandler#setDocumentLocator */ public void setDocumentLocator(Locator locator) { if (DEBUG) System.out.println("TransformerHandlerImpl#setDocumentLocator: " + locator.getSystemId()); this.m_locator = locator; if(null == m_baseSystemID) { setSystemId(locator.getSystemId()); } if (m_contentHandler != null) { m_contentHandler.setDocumentLocator(locator); } } /** * Filter a start document event. * * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#startDocument */ public void startDocument() throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#startDocument"); m_insideParse = true; // Thread listener = new Thread(m_transformer); if (m_contentHandler != null) { //m_transformer.setTransformThread(listener); if(m_incremental) { m_transformer.setSourceTreeDocForThread(m_dtm.getDocument()); int cpriority = Thread.currentThread().getPriority(); // runTransformThread is equivalent with the 2.0.1 code, // except that the Thread may come from a pool. m_transformer.runTransformThread( cpriority ); } // This is now done _last_, because IncrementalSAXSource_Filter // will immediately go into a "wait until events are requested" // pause. I believe that will close our timing window. // %REVIEW% m_contentHandler.startDocument(); } //listener.setDaemon(false); //listener.start(); } /** * Filter an end document event. * * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#endDocument */ public void endDocument() throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#endDocument"); m_insideParse = false; if (m_contentHandler != null) { m_contentHandler.endDocument(); } if(m_incremental) { m_transformer.waitTransformThread(); } else { m_transformer.setSourceTreeDocForThread(m_dtm.getDocument()); m_transformer.run(); } /* Thread transformThread = m_transformer.getTransformThread(); if (null != transformThread) { try { // This should wait until the transformThread is considered not alive. transformThread.join(); if (!m_transformer.hasTransformThreadErrorCatcher()) { Exception e = m_transformer.getExceptionThrown(); if (null != e) throw new org.xml.sax.SAXException(e); } m_transformer.setTransformThread(null); } catch (InterruptedException ie){} }*/ } /** * Filter a start Namespace prefix mapping event. * * @param prefix The Namespace prefix. * @param uri The Namespace URI. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#startPrefixMapping */ public void startPrefixMapping(String prefix, String uri) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#startPrefixMapping: " + prefix + ", " + uri); if (m_contentHandler != null) { m_contentHandler.startPrefixMapping(prefix, uri); } } /** * Filter an end Namespace prefix mapping event. * * @param prefix The Namespace prefix. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#endPrefixMapping */ public void endPrefixMapping(String prefix) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#endPrefixMapping: " + prefix); if (m_contentHandler != null) { m_contentHandler.endPrefixMapping(prefix); } } /** * Filter a start element event. * * @param uri The element's Namespace URI, or the empty string. * @param localName The element's local name, or the empty string. * @param qName The element's qualified (prefixed) name, or the empty * string. * @param atts The element's attributes. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#startElement */ public void startElement( String uri, String localName, String qName, Attributes atts) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#startElement: " + qName); if (m_contentHandler != null) { m_contentHandler.startElement(uri, localName, qName, atts); } } /** * Filter an end element event. * * @param uri The element's Namespace URI, or the empty string. * @param localName The element's local name, or the empty string. * @param qName The element's qualified (prefixed) name, or the empty * string. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#endElement */ public void endElement(String uri, String localName, String qName) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#endElement: " + qName); if (m_contentHandler != null) { m_contentHandler.endElement(uri, localName, qName); } } /** * Filter a character data event. * * @param ch An array of characters. * @param start The starting position in the array. * @param length The number of characters to use from the array. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#characters */ public void characters(char ch[], int start, int length) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#characters: " + start + ", " + length); if (m_contentHandler != null) { m_contentHandler.characters(ch, start, length); } } /** * Filter an ignorable whitespace event. * * @param ch An array of characters. * @param start The starting position in the array. * @param length The number of characters to use from the array. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#ignorableWhitespace */ public void ignorableWhitespace(char ch[], int start, int length) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#ignorableWhitespace: " + start + ", " + length); if (m_contentHandler != null) { m_contentHandler.ignorableWhitespace(ch, start, length); } } /** * Filter a processing instruction event. * * @param target The processing instruction target. * @param data The text following the target. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#processingInstruction */ public void processingInstruction(String target, String data) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#processingInstruction: " + target + ", " + data); if (m_contentHandler != null) { m_contentHandler.processingInstruction(target, data); } } /** * Filter a skipped entity event. * * @param name The name of the skipped entity. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ContentHandler#skippedEntity */ public void skippedEntity(String name) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#skippedEntity: " + name); if (m_contentHandler != null) { m_contentHandler.skippedEntity(name); } } //////////////////////////////////////////////////////////////////// // Implementation of org.xml.sax.ErrorHandler. //////////////////////////////////////////////////////////////////// /** * Filter a warning event. * * @param e The nwarning as an exception. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ErrorHandler#warning */ public void warning(SAXParseException e) throws SAXException { // This is not great, but we really would rather have the error // handler be the error listener if it is a error handler. Coroutine's fatalError // can't really be configured, so I think this is the best thing right now // for error reporting. Possibly another JAXP 1.1 hole. -sb javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener(); if(errorListener instanceof ErrorHandler) { ((ErrorHandler)errorListener).warning(e); } else { try { errorListener.warning(new javax.xml.transform.TransformerException(e)); } catch(javax.xml.transform.TransformerException te) { throw e; } } } /** * Filter an error event. * * @param e The error as an exception. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ErrorHandler#error */ public void error(SAXParseException e) throws SAXException { // %REVIEW% I don't think this should be called. -sb // clearCoRoutine(e); // This is not great, but we really would rather have the error // handler be the error listener if it is a error handler. Coroutine's fatalError // can't really be configured, so I think this is the best thing right now // for error reporting. Possibly another JAXP 1.1 hole. -sb javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener(); if(errorListener instanceof ErrorHandler) { ((ErrorHandler)errorListener).error(e); if(null != m_errorHandler) m_errorHandler.error(e); // may not be called. } else { try { errorListener.error(new javax.xml.transform.TransformerException(e)); if(null != m_errorHandler) m_errorHandler.error(e); // may not be called. } catch(javax.xml.transform.TransformerException te) { throw e; } } } /** * Filter a fatal error event. * * @param e The error as an exception. * @throws SAXException The client may throw * an exception during processing. * @see org.xml.sax.ErrorHandler#fatalError */ public void fatalError(SAXParseException e) throws SAXException { if(null != m_errorHandler) { try { m_errorHandler.fatalError(e); } catch(SAXParseException se) { // ignore } // clearCoRoutine(e); } // This is not great, but we really would rather have the error // handler be the error listener if it is a error handler. Coroutine's fatalError // can't really be configured, so I think this is the best thing right now // for error reporting. Possibly another JAXP 1.1 hole. -sb javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener(); if(errorListener instanceof ErrorHandler) { ((ErrorHandler)errorListener).fatalError(e); if(null != m_errorHandler) m_errorHandler.fatalError(e); // may not be called. } else { try { errorListener.fatalError(new javax.xml.transform.TransformerException(e)); if(null != m_errorHandler) m_errorHandler.fatalError(e); // may not be called. } catch(javax.xml.transform.TransformerException te) { throw e; } } } //////////////////////////////////////////////////////////////////// // Implementation of org.xml.sax.ext.LexicalHandler. //////////////////////////////////////////////////////////////////// /** * Report the start of DTD declarations, if any. * *

Any declarations are assumed to be in the internal subset * unless otherwise indicated by a {@link #startEntity startEntity} * event.

* *

Note that the start/endDTD events will appear within * the start/endDocument events from ContentHandler and * before the first startElement event.

* * @param name The document type name. * @param publicId The declared public identifier for the * external DTD subset, or null if none was declared. * @param systemId The declared system identifier for the * external DTD subset, or null if none was declared. * @throws SAXException The application may raise an * exception. * @see #endDTD * @see #startEntity */ public void startDTD(String name, String publicId, String systemId) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#startDTD: " + name + ", " + publicId + ", " + systemId); if (null != m_lexicalHandler) { m_lexicalHandler.startDTD(name, publicId, systemId); } } /** * Report the end of DTD declarations. * * @throws SAXException The application may raise an exception. * @see #startDTD */ public void endDTD() throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#endDTD"); if (null != m_lexicalHandler) { m_lexicalHandler.endDTD(); } } /** * Report the beginning of an entity in content. * *

NOTE: entity references in attribute * values -- and the start and end of the document entity -- * are never reported.

* *

The start and end of the external DTD subset are reported * using the pseudo-name "[dtd]". All other events must be * properly nested within start/end entity events.

* *

Note that skipped entities will be reported through the * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity} * event, which is part of the ContentHandler interface.

* * @param name The name of the entity. If it is a parameter * entity, the name will begin with '%'. * @throws SAXException The application may raise an exception. * @see #endEntity * @see org.xml.sax.ext.DeclHandler#internalEntityDecl * @see org.xml.sax.ext.DeclHandler#externalEntityDecl */ public void startEntity(String name) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#startEntity: " + name); if (null != m_lexicalHandler) { m_lexicalHandler.startEntity(name); } } /** * Report the end of an entity. * * @param name The name of the entity that is ending. * @throws SAXException The application may raise an exception. * @see #startEntity */ public void endEntity(String name) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#endEntity: " + name); if (null != m_lexicalHandler) { m_lexicalHandler.endEntity(name); } } /** * Report the start of a CDATA section. * *

The contents of the CDATA section will be reported through * the regular {@link org.xml.sax.ContentHandler#characters * characters} event.

* * @throws SAXException The application may raise an exception. * @see #endCDATA */ public void startCDATA() throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#startCDATA"); if (null != m_lexicalHandler) { m_lexicalHandler.startCDATA(); } } /** * Report the end of a CDATA section. * * @throws SAXException The application may raise an exception. * @see #startCDATA */ public void endCDATA() throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#endCDATA"); if (null != m_lexicalHandler) { m_lexicalHandler.endCDATA(); } } /** * Report an XML comment anywhere in the document. * *

This callback will be used for comments inside or outside the * document element, including comments in the external DTD * subset (if read).

* * @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 SAXException The application may raise an exception. */ public void comment(char ch[], int start, int length) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#comment: " + start + ", " + length); if (null != m_lexicalHandler) { m_lexicalHandler.comment(ch, start, length); } } //////////////////////////////////////////////////////////////////// // Implementation of org.xml.sax.ext.DeclHandler. //////////////////////////////////////////////////////////////////// /** * Report an element type declaration. * *

The content model will consist of the string "EMPTY", the * string "ANY", or a parenthesised group, optionally followed * by an occurrence indicator. The model will be normalized so * that all whitespace is removed,and will include the enclosing * parentheses.

* * @param name The element type name. * @param model The content model as a normalized string. * @throws SAXException The application may raise an exception. */ public void elementDecl(String name, String model) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#elementDecl: " + name + ", " + model); if (null != m_declHandler) { m_declHandler.elementDecl(name, model); } } /** * Report an attribute type declaration. * *

Only the effective (first) declaration for an attribute will * be reported. The type will be one of the strings "CDATA", * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", * "ENTITIES", or "NOTATION", or a parenthesized token group with * the separator "|" and all whitespace removed.

* * @param eName The name of the associated element. * @param aName The name of the attribute. * @param type A string representing the attribute type. * @param valueDefault A string representing the attribute default * ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if * none of these applies. * @param value A string representing the attribute's default value, * or null if there is none. * @throws SAXException The application may raise an exception. */ public void attributeDecl( String eName, String aName, String type, String valueDefault, String value) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#attributeDecl: " + eName + ", " + aName + ", etc..."); if (null != m_declHandler) { m_declHandler.attributeDecl(eName, aName, type, valueDefault, value); } } /** * Report an internal entity declaration. * *

Only the effective (first) declaration for each entity * will be reported.

* * @param name The name of the entity. If it is a parameter * entity, the name will begin with '%'. * @param value The replacement text of the entity. * @throws SAXException The application may raise an exception. * @see #externalEntityDecl * @see org.xml.sax.DTDHandler#unparsedEntityDecl */ public void internalEntityDecl(String name, String value) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#internalEntityDecl: " + name + ", " + value); if (null != m_declHandler) { m_declHandler.internalEntityDecl(name, value); } } /** * Report a parsed external entity declaration. * *

Only the effective (first) declaration for each entity * will be reported.

* * @param name The name of the entity. If it is a parameter * entity, the name will begin with '%'. * @param publicId The declared public identifier of the entity, or * null if none was declared. * @param systemId The declared system identifier of the entity. * @throws SAXException The application may raise an exception. * @see #internalEntityDecl * @see org.xml.sax.DTDHandler#unparsedEntityDecl */ public void externalEntityDecl( String name, String publicId, String systemId) throws SAXException { if (DEBUG) System.out.println("TransformerHandlerImpl#externalEntityDecl: " + name + ", " + publicId + ", " + systemId); if (null != m_declHandler) { m_declHandler.externalEntityDecl(name, publicId, systemId); } } //////////////////////////////////////////////////////////////////// // Internal state. //////////////////////////////////////////////////////////////////// /** Set to true for diagnostics output. */ private static boolean DEBUG = false; /** * The transformer this will use to transform a * source tree into a result tree. */ private TransformerImpl m_transformer; /** The system ID to use as a base for relative URLs. */ private String m_baseSystemID; /** The result for the transformation. */ private Result m_result = null; /** The locator for this TransformerHandler. */ private Locator m_locator = null; /** The entity resolver to aggregate to. */ private EntityResolver m_entityResolver = null; /** The DTD handler to aggregate to. */ private DTDHandler m_dtdHandler = null; /** The content handler to aggregate to. */ private ContentHandler m_contentHandler = null; /** The error handler to aggregate to. */ private ErrorHandler m_errorHandler = null; /** The lexical handler to aggregate to. */ private LexicalHandler m_lexicalHandler = null; /** The decl handler to aggregate to. */ private DeclHandler m_declHandler = null; /** The Document Table Instance we are transforming. */ DTM m_dtm; }