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 * &!ELEMENT xsl:attribute %char-template;> 38 * &!ATTLIST xsl:attribute 39 * name %avt; #REQUIRED 40 * namespace %avt; #IMPLIED 41 * %space-att; 42 * & 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