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 */
21package org.apache.xalan.templates;
22
23import javax.xml.transform.TransformerException;
24
25import org.apache.xalan.res.XSLTErrorResources;
26import org.apache.xalan.transformer.TransformerImpl;
27import org.apache.xml.utils.XML11Char;
28import 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 */
42public 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   */
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   */
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   */
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   */
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   */
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    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   */
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