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: ElemAttribute.java 469304 2006-10-30 22:29:47Z 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.serializer.NamespaceMappings;
028 import org.apache.xml.serializer.SerializationHandler;
029 import org.apache.xml.utils.QName;
030 import org.apache.xml.utils.XML11Char;
031
032 import org.xml.sax.SAXException;
033
034 /**
035 * Implement xsl:attribute.
036 * <pre>
037 * &!ELEMENT xsl:attribute %char-template;>
038 * &!ATTLIST xsl:attribute
039 * name %avt; #REQUIRED
040 * namespace %avt; #IMPLIED
041 * %space-att;
042 * &
043 * </pre>
044 * @see <a href="http://www.w3.org/TR/xslt#creating-attributes">creating-attributes in XSLT Specification</a>
045 * @xsl.usage advanced
046 */
047 public class ElemAttribute extends ElemElement
048 {
049 static final long serialVersionUID = 8817220961566919187L;
050
051 /**
052 * Get an int constant identifying the type of element.
053 * @see org.apache.xalan.templates.Constants
054 *
055 * @return The token ID for this element
056 */
057 public int getXSLToken()
058 {
059 return Constants.ELEMNAME_ATTRIBUTE;
060 }
061
062 /**
063 * Return the node name.
064 *
065 * @return The element name
066 */
067 public String getNodeName()
068 {
069 return Constants.ELEMNAME_ATTRIBUTE_STRING;
070 }
071
072 /**
073 * Create an attribute in the result tree.
074 * @see <a href="http://www.w3.org/TR/xslt#creating-attributes">creating-attributes in XSLT Specification</a>
075 *
076 * @param transformer non-null reference to the the current transform-time state.
077 *
078 * @throws TransformerException
079 */
080 // public void execute(
081 // TransformerImpl transformer)
082 // throws TransformerException
083 // {
084 //SerializationHandler rhandler = transformer.getSerializationHandler();
085
086 // If they are trying to add an attribute when there isn't an
087 // element pending, it is an error.
088 // I don't think we need this check here because it is checked in
089 // ResultTreeHandler.addAttribute. (is)
090 // if (!rhandler.isElementPending())
091 // {
092 // // Make sure the trace event is sent.
093 // if (TransformerImpl.S_DEBUG)
094 // transformer.getTraceManager().fireTraceEvent(this);
095 //
096 // XPathContext xctxt = transformer.getXPathContext();
097 // int sourceNode = xctxt.getCurrentNode();
098 // String attrName = m_name_avt.evaluate(xctxt, sourceNode, this);
099 // 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 */
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 */
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 */
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 */
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 */
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 }