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 }