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: ElemAttribute.java 469304 2006-10-30 22:29:47Z 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.serializer.NamespaceMappings;
28 import org.apache.xml.serializer.SerializationHandler;
29 import org.apache.xml.utils.QName;
30 import org.apache.xml.utils.XML11Char;
31 
32 import org.xml.sax.SAXException;
33 
34 /**
35  * Implement xsl:attribute.
36  * <pre>
37  * &amp;!ELEMENT xsl:attribute %char-template;>
38  * &amp;!ATTLIST xsl:attribute
39  *   name %avt; #REQUIRED
40  *   namespace %avt; #IMPLIED
41  *   %space-att;
42  * &amp;
43  * </pre>
44  * @see <a href="http://www.w3.org/TR/xslt#creating-attributes">creating-attributes in XSLT Specification</a>
45  * @xsl.usage advanced
46  */
47 public class ElemAttribute extends ElemElement
48 {
49     static final long serialVersionUID = 8817220961566919187L;
50 
51   /**
52    * Get an int constant identifying the type of element.
53    * @see org.apache.xalan.templates.Constants
54    *
55    * @return The token ID for this element
56    */
getXSLToken()57   public int getXSLToken()
58   {
59     return Constants.ELEMNAME_ATTRIBUTE;
60   }
61 
62   /**
63    * Return the node name.
64    *
65    * @return The element name
66    */
getNodeName()67   public String getNodeName()
68   {
69     return Constants.ELEMNAME_ATTRIBUTE_STRING;
70   }
71 
72   /**
73    * Create an attribute in the result tree.
74    * @see <a href="http://www.w3.org/TR/xslt#creating-attributes">creating-attributes in XSLT Specification</a>
75    *
76    * @param transformer non-null reference to the the current transform-time state.
77    *
78    * @throws TransformerException
79    */
80 //  public void execute(
81 //          TransformerImpl transformer)
82 //            throws TransformerException
83 //  {
84     //SerializationHandler rhandler = transformer.getSerializationHandler();
85 
86     // If they are trying to add an attribute when there isn't an
87     // element pending, it is an error.
88     // I don't think we need this check here because it is checked in
89     // ResultTreeHandler.addAttribute.  (is)
90 //    if (!rhandler.isElementPending())
91 //    {
92 //      // Make sure the trace event is sent.
93 //      if (TransformerImpl.S_DEBUG)
94 //        transformer.getTraceManager().fireTraceEvent(this);
95 //
96 //      XPathContext xctxt = transformer.getXPathContext();
97 //      int sourceNode = xctxt.getCurrentNode();
98 //      String attrName = m_name_avt.evaluate(xctxt, sourceNode, this);
99 //      transformer.getMsgMgr().warn(this,
100 //                                   XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_POSITION,
101 //                                   new Object[]{ attrName });
102 //
103 //      if (TransformerImpl.S_DEBUG)
104 //        transformer.getTraceManager().fireTraceEndEvent(this);
105 //      return;
106 //
107 //      // warn(templateChild, sourceNode, "Trying to add attribute after element child has been added, ignoring...");
108 //    }
109 
110 //    super.execute(transformer);
111 
112 //  }
113 
114   /**
115    * Resolve the namespace into a prefix.  At this level, if no prefix exists,
116    * then return a manufactured prefix.
117    *
118    * @param rhandler The current result tree handler.
119    * @param prefix The probable prefix if already known.
120    * @param nodeNamespace  The namespace, which should not be null.
121    *
122    * @return The prefix to be used.
123    */
resolvePrefix(SerializationHandler rhandler, String prefix, String nodeNamespace)124   protected String resolvePrefix(SerializationHandler rhandler,
125                                  String prefix, String nodeNamespace)
126     throws TransformerException
127   {
128 
129     if (null != prefix && (prefix.length() == 0 || prefix.equals("xmlns")))
130     {
131       // Since we can't use default namespace, in this case we try and
132       // see if a prefix has already been defined or this namespace.
133       prefix = rhandler.getPrefix(nodeNamespace);
134 
135       // System.out.println("nsPrefix: "+nsPrefix);
136       if (null == prefix || prefix.length() == 0 || prefix.equals("xmlns"))
137       {
138         if(nodeNamespace.length() > 0)
139         {
140             NamespaceMappings prefixMapping = rhandler.getNamespaceMappings();
141             prefix = prefixMapping.generateNextPrefix();
142         }
143         else
144           prefix = "";
145       }
146     }
147     return prefix;
148   }
149 
150   /**
151    * Validate that the node name is good.
152    *
153    * @param nodeName Name of the node being constructed, which may be null.
154    *
155    * @return true if the node name is valid, false otherwise.
156    */
validateNodeName(String nodeName)157    protected boolean validateNodeName(String nodeName)
158    {
159       if(null == nodeName)
160         return false;
161       if(nodeName.equals("xmlns"))
162         return false;
163       return XML11Char.isXML11ValidQName(nodeName);
164    }
165 
166   /**
167    * Construct a node in the result tree.  This method is overloaded by
168    * xsl:attribute. At this class level, this method creates an element.
169    *
170    * @param nodeName The name of the node, which may be null.
171    * @param prefix The prefix for the namespace, which may be null.
172    * @param nodeNamespace The namespace of the node, which may be null.
173    * @param transformer non-null reference to the the current transform-time state.
174    * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
175    * @param mode reference, which may be null, to the <a href="http://www.w3.org/TR/xslt#modes">current mode</a>.
176    *
177    * @throws TransformerException
178    */
constructNode( String nodeName, String prefix, String nodeNamespace, TransformerImpl transformer)179   void constructNode(
180           String nodeName, String prefix, String nodeNamespace, TransformerImpl transformer)
181             throws TransformerException
182   {
183 
184     if(null != nodeName && nodeName.length() > 0)
185     {
186       SerializationHandler rhandler = transformer.getSerializationHandler();
187 
188       // Evaluate the value of this attribute
189       String val = transformer.transformToString(this);
190       try
191       {
192         // Let the result tree handler add the attribute and its String value.
193         String localName = QName.getLocalPart(nodeName);
194         if(prefix != null && prefix.length() > 0){
195             rhandler.addAttribute(nodeNamespace, localName, nodeName, "CDATA", val, true);
196         }else{
197             rhandler.addAttribute("", localName, nodeName, "CDATA", val, true);
198         }
199       }
200       catch (SAXException e)
201       {
202       }
203     }
204   }
205 
206 
207   /**
208    * Add a child to the child list.
209    * <!ELEMENT xsl:attribute %char-template;>
210    * <!ATTLIST xsl:attribute
211    *   name %avt; #REQUIRED
212    *   namespace %avt; #IMPLIED
213    *   %space-att;
214    * >
215    *
216    * @param newChild Child to append to the list of this node's children
217    *
218    * @return The node we just appended to the children list
219    *
220    * @throws DOMException
221    */
appendChild(ElemTemplateElement newChild)222   public ElemTemplateElement appendChild(ElemTemplateElement newChild)
223   {
224 
225     int type = ((ElemTemplateElement) newChild).getXSLToken();
226 
227     switch (type)
228     {
229 
230     // char-instructions
231     case Constants.ELEMNAME_TEXTLITERALRESULT :
232     case Constants.ELEMNAME_APPLY_TEMPLATES :
233     case Constants.ELEMNAME_APPLY_IMPORTS :
234     case Constants.ELEMNAME_CALLTEMPLATE :
235     case Constants.ELEMNAME_FOREACH :
236     case Constants.ELEMNAME_VALUEOF :
237     case Constants.ELEMNAME_COPY_OF :
238     case Constants.ELEMNAME_NUMBER :
239     case Constants.ELEMNAME_CHOOSE :
240     case Constants.ELEMNAME_IF :
241     case Constants.ELEMNAME_TEXT :
242     case Constants.ELEMNAME_COPY :
243     case Constants.ELEMNAME_VARIABLE :
244     case Constants.ELEMNAME_MESSAGE :
245 
246       // instructions
247       // case Constants.ELEMNAME_PI:
248       // case Constants.ELEMNAME_COMMENT:
249       // case Constants.ELEMNAME_ELEMENT:
250       // case Constants.ELEMNAME_ATTRIBUTE:
251       break;
252     default :
253       error(XSLTErrorResources.ER_CANNOT_ADD,
254             new Object[]{ newChild.getNodeName(),
255                           this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +
256 
257     //" to " + this.m_elemName);
258     }
259 
260     return super.appendChild(newChild);
261   }
262 	/**
263 	 * @see ElemElement#setName(AVT)
264 	 */
setName(AVT v)265 	public void setName(AVT v) {
266         if (v.isSimple())
267         {
268             if (v.getSimpleString().equals("xmlns"))
269             {
270                 throw new IllegalArgumentException();
271             }
272         }
273 		super.setName(v);
274 	}
275 
276 }
277