001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: TreeWalker2Result.java 468645 2006-10-28 06:57:24Z minchau $
020     */
021    package org.apache.xalan.transformer;
022    
023    import org.apache.xalan.serialize.SerializerUtils;
024    import org.apache.xml.dtm.DTM;
025    import org.apache.xml.dtm.ref.DTMTreeWalker;
026    import org.apache.xml.serializer.SerializationHandler;
027    import org.apache.xpath.XPathContext;
028    
029    /**
030     * Handle a walk of a tree, but screen out attributes for
031     * the result tree.
032     * @xsl.usage internal
033     */
034    public class TreeWalker2Result extends DTMTreeWalker
035    {
036    
037      /** The transformer instance          */
038      TransformerImpl m_transformer;
039    
040      /** The result tree handler          */
041      SerializationHandler m_handler;
042    
043      /** Node where to start the tree walk           */
044      int m_startNode;
045    
046      /**
047       * Constructor.
048       *
049       * @param transformer Non-null transformer instance
050       * @param handler The Result tree handler to use
051       */
052      public TreeWalker2Result(TransformerImpl transformer,
053                               SerializationHandler handler)
054      {
055    
056        super(handler, null);
057    
058        m_transformer = transformer;
059        m_handler = handler;
060      }
061    
062      /**
063       * Perform a pre-order traversal non-recursive style.
064       *
065       * @param pos Start node for traversal
066       *
067       * @throws TransformerException
068       */
069      public void traverse(int pos) throws org.xml.sax.SAXException
070      {
071        m_dtm = m_transformer.getXPathContext().getDTM(pos);
072        m_startNode = pos;
073    
074        super.traverse(pos);
075      }
076            
077            /**
078       * End processing of given node 
079       *
080       *
081       * @param node Node we just finished processing
082       *
083       * @throws org.xml.sax.SAXException
084       */
085      protected void endNode(int node) throws org.xml.sax.SAXException
086      {
087        super.endNode(node);
088        if(DTM.ELEMENT_NODE == m_dtm.getNodeType(node))
089        {
090          m_transformer.getXPathContext().popCurrentNode();
091        }
092      }
093    
094      /**
095       * Start traversal of the tree at the given node
096       *
097       *
098       * @param node Starting node for traversal
099       *
100       * @throws TransformerException
101       */
102      protected void startNode(int node) throws org.xml.sax.SAXException
103      {
104    
105        XPathContext xcntxt = m_transformer.getXPathContext();
106        try
107        {
108          
109          if (DTM.ELEMENT_NODE == m_dtm.getNodeType(node))
110          {
111            xcntxt.pushCurrentNode(node);                   
112                                            
113            if(m_startNode != node)
114            {
115              super.startNode(node);
116            }
117            else
118            {
119              String elemName = m_dtm.getNodeName(node);
120              String localName = m_dtm.getLocalName(node);
121              String namespace = m_dtm.getNamespaceURI(node);
122                                            
123              //xcntxt.pushCurrentNode(node);       
124              // SAX-like call to allow adding attributes afterwards
125              m_handler.startElement(namespace, localName, elemName);
126              boolean hasNSDecls = false;
127              DTM dtm = m_dtm;
128              for (int ns = dtm.getFirstNamespaceNode(node, true); 
129                   DTM.NULL != ns; ns = dtm.getNextNamespaceNode(node, ns, true))
130              {
131                SerializerUtils.ensureNamespaceDeclDeclared(m_handler,dtm, ns);
132              }
133                                                    
134                                                    
135              for (int attr = dtm.getFirstAttribute(node); 
136                   DTM.NULL != attr; attr = dtm.getNextAttribute(attr))
137              {
138                SerializerUtils.addAttribute(m_handler, attr);
139              }
140            }
141                                    
142          }
143          else
144          {
145            xcntxt.pushCurrentNode(node);
146            super.startNode(node);
147            xcntxt.popCurrentNode();
148          }
149        }
150        catch(javax.xml.transform.TransformerException te)
151        {
152          throw new org.xml.sax.SAXException(te);
153        }
154      }
155    }