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: ElemPI.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.xml.utils.XML11Char;
28 import org.apache.xpath.XPathContext;
29 
30 /**
31  * Implement xsl:processing-instruction.
32  * <pre>
33  * <!ELEMENT xsl:processing-instruction %char-template;>
34  * <!ATTLIST xsl:processing-instruction
35  *   name %avt; #REQUIRED
36  *   %space-att;
37  * >
38  * </pre>
39  * @see <a href="http://www.w3.org/TR/xslt#section-Creating-Processing-Instructions">section-Creating-Processing-Instructions in XSLT Specification</a>
40  * @xsl.usage advanced
41  */
42 public class ElemPI extends ElemTemplateElement
43 {
44     static final long serialVersionUID = 5621976448020889825L;
45 
46   /**
47    * The xsl:processing-instruction element has a required name
48    * attribute that specifies the name of the processing instruction node.
49    * The value of the name attribute is interpreted as an
50    * attribute value template.
51    * @serial
52    */
53   private AVT m_name_atv = null;
54 
55   /**
56    * Set the "name" attribute.
57    * DJD
58    *
59    * @param v Value for the name attribute
60    */
setName(AVT v)61   public void setName(AVT v)
62   {
63     m_name_atv = v;
64   }
65 
66   /**
67    * Get the "name" attribute.
68    * DJD
69    *
70    * @return The value of the "name" attribute
71    */
getName()72   public AVT getName()
73   {
74     return m_name_atv;
75   }
76 
77   /**
78    * This function is called after everything else has been
79    * recomposed, and allows the template to set remaining
80    * values that may be based on some other property that
81    * depends on recomposition.
82    */
compose(StylesheetRoot sroot)83   public void compose(StylesheetRoot sroot) throws TransformerException
84   {
85     super.compose(sroot);
86     java.util.Vector vnames = sroot.getComposeState().getVariableNames();
87     if(null != m_name_atv)
88       m_name_atv.fixupVariables(vnames, sroot.getComposeState().getGlobalsSize());
89   }
90 
91 
92 
93   /**
94    * Get an int constant identifying the type of element.
95    * @see org.apache.xalan.templates.Constants
96    *
97    * @return The token ID for the element
98    */
getXSLToken()99   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    */
getNodeName()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    */
execute( TransformerImpl transformer)124   public void execute(
125           TransformerImpl transformer)
126             throws TransformerException
127   {
128 
129     XPathContext xctxt = transformer.getXPathContext();
130     int sourceNode = xctxt.getCurrentNode();
131 
132     String piName = m_name_atv == null ? null : m_name_atv.evaluate(xctxt, sourceNode, this);
133 
134     // Ignore processing instruction if name is null
135     if (piName == null) return;
136 
137     if (piName.equalsIgnoreCase("xml"))
138     {
139      	transformer.getMsgMgr().warn(
140         this, XSLTErrorResources.WG_PROCESSINGINSTRUCTION_NAME_CANT_BE_XML,
141               new Object[]{ Constants.ATTRNAME_NAME, piName });
142 		return;
143     }
144 
145     // Only check if an avt was used (ie. this wasn't checked at compose time.)
146     // Ignore processing instruction, if invalid
147     else if ((!m_name_atv.isSimple()) && (!XML11Char.isXML11ValidNCName(piName)))
148     {
149      	transformer.getMsgMgr().warn(
150         this, XSLTErrorResources.WG_PROCESSINGINSTRUCTION_NOTVALID_NCNAME,
151               new Object[]{ Constants.ATTRNAME_NAME, piName });
152 		return;
153     }
154 
155     // Note the content model is:
156     // <!ENTITY % instructions "
157     // %char-instructions;
158     // | xsl:processing-instruction
159     // | xsl:comment
160     // | xsl:element
161     // | xsl:attribute
162     // ">
163     String data = transformer.transformToString(this);
164 
165     try
166     {
167       transformer.getResultTreeHandler().processingInstruction(piName, data);
168     }
169     catch(org.xml.sax.SAXException se)
170     {
171       throw new TransformerException(se);
172     }
173   }
174 
175   /**
176    * Add a child to the child list.
177    *
178    * @param newChild Child to add to child list
179    *
180    * @return The child just added to the child list
181    *
182    * @throws DOMException
183    */
appendChild(ElemTemplateElement newChild)184   public ElemTemplateElement appendChild(ElemTemplateElement newChild)
185   {
186 
187     int type = ((ElemTemplateElement) newChild).getXSLToken();
188 
189     switch (type)
190     {
191 
192     // char-instructions
193     case Constants.ELEMNAME_TEXTLITERALRESULT :
194     case Constants.ELEMNAME_APPLY_TEMPLATES :
195     case Constants.ELEMNAME_APPLY_IMPORTS :
196     case Constants.ELEMNAME_CALLTEMPLATE :
197     case Constants.ELEMNAME_FOREACH :
198     case Constants.ELEMNAME_VALUEOF :
199     case Constants.ELEMNAME_COPY_OF :
200     case Constants.ELEMNAME_NUMBER :
201     case Constants.ELEMNAME_CHOOSE :
202     case Constants.ELEMNAME_IF :
203     case Constants.ELEMNAME_TEXT :
204     case Constants.ELEMNAME_COPY :
205     case Constants.ELEMNAME_VARIABLE :
206     case Constants.ELEMNAME_MESSAGE :
207 
208       // instructions
209       // case Constants.ELEMNAME_PI:
210       // case Constants.ELEMNAME_COMMENT:
211       // case Constants.ELEMNAME_ELEMENT:
212       // case Constants.ELEMNAME_ATTRIBUTE:
213       break;
214     default :
215       error(XSLTErrorResources.ER_CANNOT_ADD,
216             new Object[]{ newChild.getNodeName(),
217                           this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +
218 
219     //" to " + this.m_elemName);
220     }
221 
222     return super.appendChild(newChild);
223   }
224 }
225