Home | History | Annotate | Download | only in templates
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: ElemCopyOf.java 468643 2006-10-28 06:56:03Z minchau $
     20  */
     21 package org.apache.xalan.templates;
     22 
     23 import javax.xml.transform.TransformerException;
     24 
     25 import org.apache.xalan.res.XSLTErrorResources;
     26 import org.apache.xalan.transformer.TransformerImpl;
     27 import org.apache.xalan.transformer.TreeWalker2Result;
     28 import org.apache.xml.dtm.DTM;
     29 import org.apache.xml.dtm.DTMIterator;
     30 import org.apache.xml.dtm.ref.DTMTreeWalker;
     31 import org.apache.xalan.serialize.SerializerUtils;
     32 import org.apache.xml.serializer.SerializationHandler;
     33 import org.apache.xpath.XPath;
     34 import org.apache.xpath.XPathContext;
     35 import org.apache.xpath.objects.XObject;
     36 
     37 /**
     38  * Implement xsl:copy-of.
     39  * <pre>
     40  * <!ELEMENT xsl:copy-of EMPTY>
     41  * <!ATTLIST xsl:copy-of select %expr; #REQUIRED>
     42  * </pre>
     43  * @see <a href="http://www.w3.org/TR/xslt#copy-of">copy-of in XSLT Specification</a>
     44  * @xsl.usage advanced
     45  */
     46 public class ElemCopyOf extends ElemTemplateElement
     47 {
     48     static final long serialVersionUID = -7433828829497411127L;
     49 
     50   /**
     51    * The required select attribute contains an expression.
     52    * @serial
     53    */
     54   public XPath m_selectExpression = null;
     55 
     56   /**
     57    * Set the "select" attribute.
     58    * The required select attribute contains an expression.
     59    *
     60    * @param expr Expression for select attribute
     61    */
     62   public void setSelect(XPath expr)
     63   {
     64     m_selectExpression = expr;
     65   }
     66 
     67   /**
     68    * Get the "select" attribute.
     69    * The required select attribute contains an expression.
     70    *
     71    * @return Expression for select attribute
     72    */
     73   public XPath getSelect()
     74   {
     75     return m_selectExpression;
     76   }
     77 
     78   /**
     79    * This function is called after everything else has been
     80    * recomposed, and allows the template to set remaining
     81    * values that may be based on some other property that
     82    * depends on recomposition.
     83    */
     84   public void compose(StylesheetRoot sroot) throws TransformerException
     85   {
     86     super.compose(sroot);
     87 
     88     StylesheetRoot.ComposeState cstate = sroot.getComposeState();
     89     m_selectExpression.fixupVariables(cstate.getVariableNames(), cstate.getGlobalsSize());
     90   }
     91 
     92   /**
     93    * Get an int constant identifying the type of element.
     94    * @see org.apache.xalan.templates.Constants
     95    *
     96    * @return The token ID for this element
     97    */
     98   public int getXSLToken()
     99   {
    100     return Constants.ELEMNAME_COPY_OF;
    101   }
    102 
    103   /**
    104    * Return the node name.
    105    *
    106    * @return The element's name
    107    */
    108   public String getNodeName()
    109   {
    110     return Constants.ELEMNAME_COPY_OF_STRING;
    111   }
    112 
    113   /**
    114    * The xsl:copy-of element can be used to insert a result tree
    115    * fragment into the result tree, without first converting it to
    116    * a string as xsl:value-of does (see [7.6.1 Generating Text with
    117    * xsl:value-of]).
    118    *
    119    * @param transformer non-null reference to the the current transform-time state.
    120    *
    121    * @throws TransformerException
    122    */
    123   public void execute(
    124           TransformerImpl transformer)
    125             throws TransformerException
    126   {
    127     try
    128     {
    129       XPathContext xctxt = transformer.getXPathContext();
    130       int sourceNode = xctxt.getCurrentNode();
    131       XObject value = m_selectExpression.execute(xctxt, sourceNode, this);
    132 
    133       SerializationHandler handler = transformer.getSerializationHandler();
    134 
    135       if (null != value)
    136                         {
    137         int type = value.getType();
    138         String s;
    139 
    140         switch (type)
    141         {
    142         case XObject.CLASS_BOOLEAN :
    143         case XObject.CLASS_NUMBER :
    144         case XObject.CLASS_STRING :
    145           s = value.str();
    146 
    147           handler.characters(s.toCharArray(), 0, s.length());
    148           break;
    149         case XObject.CLASS_NODESET :
    150 
    151           // System.out.println(value);
    152           DTMIterator nl = value.iter();
    153 
    154           // Copy the tree.
    155           DTMTreeWalker tw = new TreeWalker2Result(transformer, handler);
    156           int pos;
    157 
    158           while (DTM.NULL != (pos = nl.nextNode()))
    159           {
    160             DTM dtm = xctxt.getDTMManager().getDTM(pos);
    161             short t = dtm.getNodeType(pos);
    162 
    163             // If we just copy the whole document, a startDoc and endDoc get
    164             // generated, so we need to only walk the child nodes.
    165             if (t == DTM.DOCUMENT_NODE)
    166             {
    167               for (int child = dtm.getFirstChild(pos); child != DTM.NULL;
    168                    child = dtm.getNextSibling(child))
    169               {
    170                 tw.traverse(child);
    171               }
    172             }
    173             else if (t == DTM.ATTRIBUTE_NODE)
    174             {
    175               SerializerUtils.addAttribute(handler, pos);
    176             }
    177             else
    178             {
    179               tw.traverse(pos);
    180             }
    181           }
    182           // nl.detach();
    183           break;
    184         case XObject.CLASS_RTREEFRAG :
    185           SerializerUtils.outputResultTreeFragment(
    186             handler, value, transformer.getXPathContext());
    187           break;
    188         default :
    189 
    190           s = value.str();
    191 
    192           handler.characters(s.toCharArray(), 0, s.length());
    193           break;
    194         }
    195       }
    196 
    197       // I don't think we want this.  -sb
    198       //  if (transformer.getDebug())
    199       //  transformer.getTraceManager().fireSelectedEvent(sourceNode, this,
    200       //  "endSelect", m_selectExpression, value);
    201 
    202     }
    203     catch(org.xml.sax.SAXException se)
    204     {
    205       throw new TransformerException(se);
    206     }
    207 
    208   }
    209 
    210   /**
    211    * Add a child to the child list.
    212    *
    213    * @param newChild Child to add to this node's child list
    214    *
    215    * @return Child just added to child list
    216    */
    217   public ElemTemplateElement appendChild(ElemTemplateElement newChild)
    218   {
    219 
    220     error(XSLTErrorResources.ER_CANNOT_ADD,
    221           new Object[]{ newChild.getNodeName(),
    222                         this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +
    223 
    224     //" to " + this.m_elemName);
    225     return null;
    226   }
    227 
    228   /**
    229    * Call the children visitors.
    230    * @param visitor The visitor whose appropriate method will be called.
    231    */
    232   protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
    233   {
    234   	if(callAttrs)
    235   		m_selectExpression.getExpression().callVisitors(m_selectExpression, visitor);
    236     super.callChildVisitors(visitor, callAttrs);
    237   }
    238 
    239 }
    240