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: ElemValueOf.java 468643 2006-10-28 06:56:03Z minchau $
020     */
021    package org.apache.xalan.templates;
022    
023    import javax.xml.transform.TransformerException;
024    
025    import org.apache.xalan.res.XSLTErrorResources;
026    import org.apache.xalan.transformer.TransformerImpl;
027    import org.apache.xml.dtm.DTM;
028    import org.apache.xml.serializer.SerializationHandler;
029    import org.apache.xpath.Expression;
030    import org.apache.xpath.XPath;
031    import org.apache.xpath.XPathContext;
032    import org.apache.xpath.objects.XObject;
033    import org.xml.sax.SAXException;
034    
035    /**
036     * Implement xsl:value-of.
037     * <pre>
038     * <!ELEMENT xsl:value-of EMPTY>
039     * <!ATTLIST xsl:value-of
040     *   select %expr; #REQUIRED
041     *   disable-output-escaping (yes|no) "no"
042     * >
043     * </pre>
044     * @see <a href="http://www.w3.org/TR/xslt#value-of">value-of in XSLT Specification</a>
045     * @xsl.usage advanced
046     */
047    public class ElemValueOf extends ElemTemplateElement
048    {
049        static final long serialVersionUID = 3490728458007586786L;
050    
051      /**
052       * The select expression to be executed.
053       * @serial
054       */
055      private XPath m_selectExpression = null;
056    
057      /**
058       * True if the pattern is a simple ".".
059       * @serial
060       */
061      private boolean m_isDot = false;
062    
063      /**
064       * Set the "select" attribute.
065       * The required select attribute is an expression; this expression
066       * is evaluated and the resulting object is converted to a
067       * string as if by a call to the string function.
068       *
069       * @param v The value to set for the "select" attribute.
070       */
071      public void setSelect(XPath v)
072      {
073    
074        if (null != v)
075        {
076          String s = v.getPatternString();
077    
078          m_isDot = (null != s) && s.equals(".");
079        }
080    
081        m_selectExpression = v;
082      }
083    
084      /**
085       * Get the "select" attribute.
086       * The required select attribute is an expression; this expression
087       * is evaluated and the resulting object is converted to a
088       * string as if by a call to the string function.
089       *
090       * @return The value of the "select" attribute.
091       */
092      public XPath getSelect()
093      {
094        return m_selectExpression;
095      }
096    
097      /**
098       * Tells if this element should disable escaping.
099       * @serial
100       */
101      private boolean m_disableOutputEscaping = false;
102    
103      /**
104       * Set the "disable-output-escaping" attribute.
105       * Normally, the xml output method escapes & and < (and
106       * possibly other characters) when outputting text nodes.
107       * This ensures that the output is well-formed XML. However,
108       * it is sometimes convenient to be able to produce output
109       * that is almost, but not quite well-formed XML; for
110       * example, the output may include ill-formed sections
111       * which are intended to be transformed into well-formed
112       * XML by a subsequent non-XML aware process. For this reason,
113       * XSLT provides a mechanism for disabling output escaping.
114       * An xsl:value-of or xsl:text element may have a
115       * disable-output-escaping attribute; the allowed values
116       * are yes or no; the default is no; if the value is yes,
117       * then a text node generated by instantiating the xsl:value-of
118       * or xsl:text element should be output without any escaping.
119       * @see <a href="http://www.w3.org/TR/xslt#disable-output-escaping">disable-output-escaping in XSLT Specification</a>
120       *
121       * @param v The value to set for the "disable-output-escaping" attribute.
122       */
123      public void setDisableOutputEscaping(boolean v)
124      {
125        m_disableOutputEscaping = v;
126      }
127    
128      /**
129       * Get the "disable-output-escaping" attribute.
130       * Normally, the xml output method escapes & and < (and
131       * possibly other characters) when outputting text nodes.
132       * This ensures that the output is well-formed XML. However,
133       * it is sometimes convenient to be able to produce output
134       * that is almost, but not quite well-formed XML; for
135       * example, the output may include ill-formed sections
136       * which are intended to be transformed into well-formed
137       * XML by a subsequent non-XML aware process. For this reason,
138       * XSLT provides a mechanism for disabling output escaping.
139       * An xsl:value-of or xsl:text element may have a
140       * disable-output-escaping attribute; the allowed values
141       * are yes or no; the default is no; if the value is yes,
142       * then a text node generated by instantiating the xsl:value-of
143       * or xsl:text element should be output without any escaping.
144       * @see <a href="http://www.w3.org/TR/xslt#disable-output-escaping">disable-output-escaping in XSLT Specification</a>
145       *
146       * @return The value of the "disable-output-escaping" attribute.
147       */
148      public boolean getDisableOutputEscaping()
149      {
150        return m_disableOutputEscaping;
151      }
152    
153      /**
154       * Get an integer representation of the element type.
155       *
156       * @return An integer representation of the element, defined in the
157       *     Constants class.
158       * @see org.apache.xalan.templates.Constants
159       */
160      public int getXSLToken()
161      {
162        return Constants.ELEMNAME_VALUEOF;
163      }
164    
165      /**
166       * This function is called after everything else has been
167       * recomposed, and allows the template to set remaining
168       * values that may be based on some other property that
169       * depends on recomposition.
170       *
171       * NEEDSDOC @param sroot
172       *
173       * @throws TransformerException
174       */
175      public void compose(StylesheetRoot sroot) throws TransformerException
176      {
177    
178        super.compose(sroot);
179    
180        java.util.Vector vnames = sroot.getComposeState().getVariableNames();
181    
182        if (null != m_selectExpression)
183          m_selectExpression.fixupVariables(
184            vnames, sroot.getComposeState().getGlobalsSize());
185      }
186    
187      /**
188       * Return the node name.
189       *
190       * @return The node name
191       */
192      public String getNodeName()
193      {
194        return Constants.ELEMNAME_VALUEOF_STRING;
195      }
196    
197      /**
198       * Execute the string expression and copy the text to the
199       * result tree.
200       * The required select attribute is an expression; this expression
201       * is evaluated and the resulting object is converted to a string
202       * as if by a call to the string function. The string specifies
203       * the string-value of the created text node. If the string is
204       * empty, no text node will be created. The created text node will
205       * be merged with any adjacent text nodes.
206       * @see <a href="http://www.w3.org/TR/xslt#value-of">value-of in XSLT Specification</a>
207       *
208       * @param transformer non-null reference to the the current transform-time state.
209       *
210       * @throws TransformerException
211       */
212      public void execute(TransformerImpl transformer) throws TransformerException
213      {
214    
215        XPathContext xctxt = transformer.getXPathContext();
216        SerializationHandler rth = transformer.getResultTreeHandler();
217    
218        if (transformer.getDebug())
219          transformer.getTraceManager().fireTraceEvent(this);
220    
221        try
222        {
223          // Optimize for "."
224          if (false && m_isDot && !transformer.getDebug())
225          {
226            int child = xctxt.getCurrentNode();
227            DTM dtm = xctxt.getDTM(child);
228    
229            xctxt.pushCurrentNode(child);
230    
231            if (m_disableOutputEscaping)
232              rth.processingInstruction(
233                javax.xml.transform.Result.PI_DISABLE_OUTPUT_ESCAPING, "");
234    
235            try
236            {
237              dtm.dispatchCharactersEvents(child, rth, false);
238            }
239            finally
240            {
241              if (m_disableOutputEscaping)
242                rth.processingInstruction(
243                  javax.xml.transform.Result.PI_ENABLE_OUTPUT_ESCAPING, "");
244    
245              xctxt.popCurrentNode();
246            }
247          }
248          else
249          {
250            xctxt.pushNamespaceContext(this);
251    
252            int current = xctxt.getCurrentNode();
253    
254            xctxt.pushCurrentNodeAndExpression(current, current);
255    
256            if (m_disableOutputEscaping)
257              rth.processingInstruction(
258                javax.xml.transform.Result.PI_DISABLE_OUTPUT_ESCAPING, "");
259    
260            try
261            {
262              Expression expr = m_selectExpression.getExpression();
263    
264              if (transformer.getDebug())
265              {
266                XObject obj = expr.execute(xctxt);
267    
268                transformer.getTraceManager().fireSelectedEvent(current, this,
269                        "select", m_selectExpression, obj);
270                obj.dispatchCharactersEvents(rth);
271              }
272              else
273              {
274                expr.executeCharsToContentHandler(xctxt, rth);
275              }
276            }
277            finally
278            {
279              if (m_disableOutputEscaping)
280                rth.processingInstruction(
281                  javax.xml.transform.Result.PI_ENABLE_OUTPUT_ESCAPING, "");
282    
283              xctxt.popNamespaceContext();
284              xctxt.popCurrentNodeAndExpression();
285            }
286          }
287        }
288        catch (SAXException se)
289        {
290          throw new TransformerException(se);
291        }
292        catch (RuntimeException re) {
293            TransformerException te = new TransformerException(re);
294            te.setLocator(this);
295            throw te;
296        }
297        finally
298        {
299          if (transformer.getDebug())
300                transformer.getTraceManager().fireTraceEndEvent(this); 
301        }
302      }
303    
304      /**
305       * Add a child to the child list.
306       *
307       * @param newChild Child to add to children list
308       *
309       * @return Child just added to children list
310       *
311       * @throws DOMException
312       */
313      public ElemTemplateElement appendChild(ElemTemplateElement newChild)
314      {
315    
316        error(XSLTErrorResources.ER_CANNOT_ADD,
317              new Object[]{ newChild.getNodeName(),
318                            this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +
319    
320        //" to " + this.m_elemName);
321        return null;
322      }
323      
324      /**
325       * Call the children visitors.
326       * @param visitor The visitor whose appropriate method will be called.
327       */
328      protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
329      {
330            if(callAttrs)
331                    m_selectExpression.getExpression().callVisitors(m_selectExpression, visitor);
332        super.callChildVisitors(visitor, callAttrs);
333      }
334    
335    }