resulttreehandler.java

来自「java jdk 1.4的源码」· Java 代码 · 共 1,929 行 · 第 1/4 页

JAVA
1,929
字号
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999 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) 1999, Lotus * Development Corporation., http://www.lotus.com.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */package org.apache.xalan.transformer;import java.util.Enumeration;import org.apache.xalan.processor.StylesheetHandler;import org.apache.xalan.res.XSLTErrorResources;import org.apache.xalan.templates.Stylesheet;import org.apache.xalan.templates.StylesheetRoot;import org.apache.xalan.templates.ElemTemplate;import org.apache.xalan.templates.ElemTemplateElement;import org.apache.xalan.trace.TraceManager;import org.apache.xalan.trace.GenerateEvent;import org.apache.xml.utils.MutableAttrListImpl;import org.apache.xml.utils.QName;import org.apache.xml.utils.TreeWalker;import org.apache.xml.utils.ObjectPool;import org.apache.xml.utils.XMLCharacterRecognizer;import org.apache.xpath.objects.XObject;import org.apache.xpath.XPathContext;import org.apache.xml.dtm.DTM;import org.apache.xml.dtm.DTMIterator;import org.apache.xml.dtm.DTMFilter;import org.xml.sax.Attributes;import org.xml.sax.ContentHandler;import org.xml.sax.ext.LexicalHandler;import org.xml.sax.SAXParseException;import org.xml.sax.SAXException;import org.xml.sax.ErrorHandler;import org.xml.sax.helpers.NamespaceSupport;import org.apache.xml.utils.NamespaceSupport2;import org.xml.sax.Locator;import javax.xml.transform.TransformerException;import javax.xml.transform.ErrorListener;import javax.xml.transform.Transformer;/** * This class is a layer between the direct calls to the result * tree content handler, and the transformer.  For one thing, * we have to delay the call to * getContentHandler().startElement(name, atts) because of the * xsl:attribute and xsl:copy calls.  In other words, * the attributes have to be fully collected before you * can call startElement. */public class ResultTreeHandler extends QueuedEvents        implements ContentHandler, LexicalHandler, TransformState,        org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.CharacterNodeHandler,        ErrorHandler{  /** Indicate whether running in Debug mode */  private static final boolean DEBUG = false;  /**   * Null constructor for object pooling.   */  public ResultTreeHandler(){}  /**   * Create a new result tree handler.  The real content   * handler will be the ContentHandler passed as an argument.   *   * @param transformer non-null transformer instance   * @param realHandler Content Handler instance   */  public ResultTreeHandler(TransformerImpl transformer,                           ContentHandler realHandler)  {    init(transformer, realHandler);  }  /**   * Initializer method.   *   * @param transformer non-null transformer instance   * @param realHandler Content Handler instance   */  public void init(TransformerImpl transformer, ContentHandler realHandler)  {    m_transformer = transformer;    // m_startDoc.setTransformer(m_transformer);    TraceManager tracer = transformer.getTraceManager();    if ((null != tracer) && tracer.hasTraceListeners())      m_tracer = tracer;    else      m_tracer = null;    // m_startDoc.setTraceManager(m_tracer);    m_contentHandler = realHandler;    // m_startDoc.setContentHandler(m_contentHandler);    if (m_contentHandler instanceof LexicalHandler)      m_lexicalHandler = (LexicalHandler) m_contentHandler;    else      m_lexicalHandler = null;    m_isTransformClient = (m_contentHandler instanceof TransformerClient);    m_cloner = new ClonerToResultTree(transformer, this);    // The stylesheet is set at a rather late stage, so I do     // this here, though it would probably be better done elsewhere.    if (null != m_transformer)      m_stylesheetRoot = m_transformer.getStylesheet();    pushDocumentEvent();  // not pending yet.  }  /**   * Bottleneck the startDocument event.   *   * @throws org.xml.sax.SAXException   */  public void startDocument() throws org.xml.sax.SAXException{}  /**   * Bottleneck the endDocument event.  This may be called   * more than once in order to make sure the pending start   * document is called.   *   * @throws org.xml.sax.SAXException   */  public void endDocument() throws org.xml.sax.SAXException  {    flushPending(true);    if (!m_docEnded)    {      m_contentHandler.endDocument();      if (null != m_tracer)      {        GenerateEvent ge =          new GenerateEvent(m_transformer,                            GenerateEvent.EVENTTYPE_ENDDOCUMENT, null);        m_tracer.fireGenerateEvent(ge);      }      m_docEnded = true;      m_docPending = false;    }  }  /**   * Bottleneck the startElement event.  This is used to "pend" an   * element, so that attributes can still be added to it before   * the real "startElement" is called on the result tree listener.   *   * @param ns Namespace URI of element   * @param localName Local part of qname of element   * @param name Name of element   * @param atts List of attributes for the element   *   * @throws org.xml.sax.SAXException   */  public void startElement(          String ns, String localName, String name, Attributes atts)            throws org.xml.sax.SAXException  {    if (DEBUG)    {      if (m_elemIsPending)        System.out.println("(ResultTreeHandler#startElement - pended: "                           + m_url + "#" + m_localName);      System.out.println("ResultTreeHandler#startElement: " + ns + "#"                         + localName);      //      if(null == ns)      //      {      //        (new RuntimeException(localName+" has a null namespace!")).printStackTrace();      //      }    }    if(m_docPending)      checkForSerializerSwitch(ns, localName);          flushPending(true);    if (!m_nsContextPushed)    {      if (DEBUG)        System.out.println(          "ResultTreeHandler#startElement - push(startElement)");      m_nsSupport.pushContext();      m_nsContextPushed = true;    }        if (ns != null)      ensurePrefixIsDeclared(ns, name);    m_name = name;    m_url = ns;    m_localName = localName;    if (null != atts)      m_attributes.addAttributes(atts);    m_elemIsPending = true;    m_elemIsEnded = false;        if(m_isTransformClient && (null != m_transformer))    {      m_snapshot.m_currentElement = m_transformer.getCurrentElement();      m_snapshot.m_currentTemplate = m_transformer.getCurrentTemplate();      m_snapshot.m_matchedTemplate = m_transformer.getMatchedTemplate();      int currentNodeHandle = m_transformer.getCurrentNode();      DTM dtm = m_transformer.getXPathContext().getDTM(currentNodeHandle);      m_snapshot.m_currentNode = dtm.getNode(currentNodeHandle);      m_snapshot.m_matchedNode = m_transformer.getMatchedNode();      m_snapshot.m_contextNodeList = m_transformer.getContextNodeList(); // TODO: Need to clone    }    // initQSE(m_startElement);    m_eventCount++;  }  /**   * Bottleneck the endElement event.   *   * @param ns Namespace URI of element   * @param localName Local part of qname of element   * @param name Name of element   *   * @throws org.xml.sax.SAXException   */  public void endElement(String ns, String localName, String name)          throws org.xml.sax.SAXException  {    if (DEBUG)    {      if (m_elemIsPending)        System.out.println("(ResultTreeHandler#endElement - pended: "                           + m_url + "#" + m_localName);      System.out.println("ResultTreeHandler#endElement: " + ns + "#"                         + localName);    }    flushPending(true);    m_contentHandler.endElement(ns, localName, name);    if (null != m_tracer)    {      GenerateEvent ge = new GenerateEvent(m_transformer,                                           GenerateEvent.EVENTTYPE_ENDELEMENT,                                           name, (Attributes)null);      m_tracer.fireGenerateEvent(ge);    }    sendEndPrefixMappings();    popEvent();    if (DEBUG)      System.out.println("ResultTreeHandler#startElement pop: " + localName);    m_nsSupport.popContext();  }  /** Indicate whether a namespace context was pushed */  boolean m_nsContextPushed = false;  /**   * Begin the scope of a prefix-URI Namespace mapping.   *   * <p>The information from this event is not necessary for   * normal Namespace processing: the SAX XML reader will   * automatically replace prefixes for element and attribute   * names when the http://xml.org/sax/features/namespaces   * feature is true (the default).</p>   *   * <p>There are cases, however, when applications need to   * use prefixes in character data or in attribute values,   * where they cannot safely be expanded automatically; the   * start/endPrefixMapping event supplies the information   * to the application to expand prefixes in those contexts   * itself, if necessary.</p>   *   * <p>Note that start/endPrefixMapping events are not   * guaranteed to be properly nested relative to each-other:   * all startPrefixMapping events will occur before the   * corresponding startElement event, and all endPrefixMapping   * events will occur after the corresponding endElement event,   * but their order is not guaranteed.</p>   *   * @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.   * @see #endPrefixMapping   * @see #startElement   */  public void startPrefixMapping(String prefix, String uri)          throws org.xml.sax.SAXException  {    startPrefixMapping(prefix, uri, true);  }  /**   * Begin the scope of a prefix-URI Namespace mapping.   *   *   * @param prefix The Namespace prefix being declared.   * @param uri The Namespace URI the prefix is mapped to.   * @param shouldFlush Indicate whether pending events needs   * to be flushed first   *   * @throws org.xml.sax.SAXException The client may throw   *            an exception during processing.   */  public void startPrefixMapping(          String prefix, String uri, boolean shouldFlush)            throws org.xml.sax.SAXException  {    if (shouldFlush)      flushPending(false);    if (!m_nsContextPushed)    {      if (DEBUG)        System.out.println(          "ResultTreeHandler#startPrefixMapping push(startPrefixMapping: "          + prefix + ")");      m_nsSupport.pushContext();      m_nsContextPushed = true;    }    if (null == prefix)      prefix = "";  // bit-o-hack, that that's OK    String existingURI = m_nsSupport.getURI(prefix);    if (null == existingURI)      existingURI = "";    if (null == uri)      uri = "";    if (!existingURI.equals(uri))    {      if (DEBUG)      {        System.out.println("ResultTreeHandler#startPrefixMapping Prefix: "                           + prefix);        System.out.println("ResultTreeHandler#startPrefixMapping uri: "                           + uri);      }      m_nsSupport.declarePrefix(prefix, uri);    }  }  /**   * End the scope of a prefix-URI mapping.   *   * <p>See startPrefixMapping for details.  This event will   * always occur after the corresponding endElement event,   * but the order of endPrefixMapping events is not otherwise   * guaranteed.</p>   *   * @param prefix The prefix that was being mapping.   * @throws org.xml.sax.SAXException The client may throw   *            an exception during processing.   * @see #startPrefixMapping   * @see #endElement   */  public void endPrefixMapping(String prefix)          throws org.xml.sax.SAXException{}  /**   * Bottleneck the characters event.   *   * @param ch Array of characters to process   * @param start start of characters in the array   * @param length Number of characters in the array   *   * @throws org.xml.sax.SAXException   */  public void characters(char ch[], int start, int length)          throws org.xml.sax.SAXException  {    // It would be nice to suppress all whitespace before the    // first element, but this is going to cause potential problems with     // text serialization and with text entities (right term?).    // So this really needs to be done at the serializer level.    /*if (m_startDoc.isPending    && XMLCharacterRecognizer.isWhiteSpace(ch, start, length))    return;*/    if (DEBUG)    {      System.out.print("ResultTreeHandler#characters: ");      int n = start + length;      for (int i = start; i < n; i++)      {        if (Character.isWhitespace(ch[i]))          System.out.print("\\" + ((int) ch[i]));        else          System.out.print(ch[i]);      }      System.out.println("");    }    flushPending(true);    m_contentHandler.characters(ch, start, length);    if (null != m_tracer)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?