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: ElemPI.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.utils.XML11Char;
028    import org.apache.xpath.XPathContext;
029    
030    /**
031     * Implement xsl:processing-instruction.
032     * <pre>
033     * <!ELEMENT xsl:processing-instruction %char-template;>
034     * <!ATTLIST xsl:processing-instruction
035     *   name %avt; #REQUIRED
036     *   %space-att;
037     * >
038     * </pre>
039     * @see <a href="http://www.w3.org/TR/xslt#section-Creating-Processing-Instructions">section-Creating-Processing-Instructions in XSLT Specification</a>
040     * @xsl.usage advanced
041     */
042    public class ElemPI extends ElemTemplateElement
043    {
044        static final long serialVersionUID = 5621976448020889825L;
045    
046      /**
047       * The xsl:processing-instruction element has a required name
048       * attribute that specifies the name of the processing instruction node.
049       * The value of the name attribute is interpreted as an
050       * attribute value template.
051       * @serial
052       */
053      private AVT m_name_atv = null;
054    
055      /**
056       * Set the "name" attribute.
057       * DJD
058       *
059       * @param v Value for the name attribute
060       */
061      public void setName(AVT v)
062      {
063        m_name_atv = v;
064      }
065    
066      /**
067       * Get the "name" attribute.
068       * DJD
069       *
070       * @return The value of the "name" attribute 
071       */
072      public AVT getName()
073      {
074        return m_name_atv;
075      }
076      
077      /**
078       * This function is called after everything else has been
079       * recomposed, and allows the template to set remaining
080       * values that may be based on some other property that
081       * depends on recomposition.
082       */
083      public void compose(StylesheetRoot sroot) throws TransformerException
084      {
085        super.compose(sroot);
086        java.util.Vector vnames = sroot.getComposeState().getVariableNames();
087        if(null != m_name_atv)
088          m_name_atv.fixupVariables(vnames, sroot.getComposeState().getGlobalsSize());
089      }
090    
091    
092    
093      /**
094       * Get an int constant identifying the type of element.
095       * @see org.apache.xalan.templates.Constants
096       *
097       * @return The token ID for the element
098       */
099      public int getXSLToken()
100      {
101        return Constants.ELEMNAME_PI;
102      }
103    
104      /**
105       * Return the node name.
106       *
107       * @return The element's name
108       */
109      public String getNodeName()
110      {
111        return Constants.ELEMNAME_PI_STRING;
112      }
113    
114      /**
115       * Create a processing instruction in the result tree.
116       * The content of the xsl:processing-instruction element is a
117       * template for the string-value of the processing instruction node.
118       * @see <a href="http://www.w3.org/TR/xslt#section-Creating-Processing-Instructions">section-Creating-Processing-Instructions in XSLT Specification</a>
119       *
120       * @param transformer non-null reference to the the current transform-time state.
121       *
122       * @throws TransformerException
123       */
124      public void execute(
125              TransformerImpl transformer)
126                throws TransformerException
127      {
128    
129        if (transformer.getDebug())
130          transformer.getTraceManager().fireTraceEvent(this);
131    
132        XPathContext xctxt = transformer.getXPathContext();
133        int sourceNode = xctxt.getCurrentNode();
134        
135        String piName = m_name_atv == null ? null : m_name_atv.evaluate(xctxt, sourceNode, this);
136        
137        // Ignore processing instruction if name is null
138        if (piName == null) return;
139    
140        if (piName.equalsIgnoreCase("xml"))
141        {
142            transformer.getMsgMgr().warn(
143            this, XSLTErrorResources.WG_PROCESSINGINSTRUCTION_NAME_CANT_BE_XML,
144                  new Object[]{ Constants.ATTRNAME_NAME, piName });
145                    return;
146        }
147        
148        // Only check if an avt was used (ie. this wasn't checked at compose time.)
149        // Ignore processing instruction, if invalid
150        else if ((!m_name_atv.isSimple()) && (!XML11Char.isXML11ValidNCName(piName)))
151        {
152            transformer.getMsgMgr().warn(
153            this, XSLTErrorResources.WG_PROCESSINGINSTRUCTION_NOTVALID_NCNAME,
154                  new Object[]{ Constants.ATTRNAME_NAME, piName });
155                    return;         
156        }
157    
158        // Note the content model is:
159        // <!ENTITY % instructions "
160        // %char-instructions;
161        // | xsl:processing-instruction
162        // | xsl:comment
163        // | xsl:element
164        // | xsl:attribute
165        // ">
166        String data = transformer.transformToString(this);
167    
168        try
169        {
170          transformer.getResultTreeHandler().processingInstruction(piName, data);
171        }
172        catch(org.xml.sax.SAXException se)
173        {
174          throw new TransformerException(se);
175        }
176        
177        if (transformer.getDebug())
178          transformer.getTraceManager().fireTraceEndEvent(this);
179      }
180    
181      /**
182       * Add a child to the child list.
183       *
184       * @param newChild Child to add to child list
185       *
186       * @return The child just added to the child list
187       *
188       * @throws DOMException
189       */
190      public ElemTemplateElement appendChild(ElemTemplateElement newChild)
191      {
192    
193        int type = ((ElemTemplateElement) newChild).getXSLToken();
194    
195        switch (type)
196        {
197    
198        // char-instructions 
199        case Constants.ELEMNAME_TEXTLITERALRESULT :
200        case Constants.ELEMNAME_APPLY_TEMPLATES :
201        case Constants.ELEMNAME_APPLY_IMPORTS :
202        case Constants.ELEMNAME_CALLTEMPLATE :
203        case Constants.ELEMNAME_FOREACH :
204        case Constants.ELEMNAME_VALUEOF :
205        case Constants.ELEMNAME_COPY_OF :
206        case Constants.ELEMNAME_NUMBER :
207        case Constants.ELEMNAME_CHOOSE :
208        case Constants.ELEMNAME_IF :
209        case Constants.ELEMNAME_TEXT :
210        case Constants.ELEMNAME_COPY :
211        case Constants.ELEMNAME_VARIABLE :
212        case Constants.ELEMNAME_MESSAGE :
213    
214          // instructions 
215          // case Constants.ELEMNAME_PI:
216          // case Constants.ELEMNAME_COMMENT:
217          // case Constants.ELEMNAME_ELEMENT:
218          // case Constants.ELEMNAME_ATTRIBUTE:
219          break;
220        default :
221          error(XSLTErrorResources.ER_CANNOT_ADD,
222                new Object[]{ newChild.getNodeName(),
223                              this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +
224    
225        //" to " + this.m_elemName);
226        }
227    
228        return super.appendChild(newChild);
229      }
230    }