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: XSLTElementProcessor.java 469688 2006-10-31 22:39:43Z minchau $ 20 */ 21 package org.apache.xalan.processor; 22 23 import java.util.ArrayList; 24 import java.util.List; 25 import java.util.Vector; 26 27 import javax.xml.transform.TransformerException; 28 29 import org.apache.xalan.res.XSLMessages; 30 import org.apache.xalan.res.XSLTErrorResources; 31 import org.apache.xalan.templates.ElemTemplateElement; 32 import org.apache.xml.utils.IntStack; 33 import org.xml.sax.Attributes; 34 import org.xml.sax.InputSource; 35 import org.xml.sax.helpers.AttributesImpl; 36 37 /** 38 * This class acts as the superclass for all stylesheet element 39 * processors, and deals with things that are common to all elements. 40 * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a> 41 */ 42 public class XSLTElementProcessor extends ElemTemplateElement 43 { 44 static final long serialVersionUID = 5597421564955304421L; 45 46 /** 47 * Construct a processor for top-level elements. 48 * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a> 49 */ XSLTElementProcessor()50 XSLTElementProcessor(){} 51 52 private IntStack m_savedLastOrder; 53 54 /** 55 * The element definition that this processor conforms to. 56 */ 57 private XSLTElementDef m_elemDef; 58 59 /** 60 * Get the element definition that belongs to this element. 61 * 62 * @return The element definition object that produced and constrains this element. 63 */ getElemDef()64 XSLTElementDef getElemDef() 65 { 66 return m_elemDef; 67 } 68 69 /** 70 * Set the element definition that belongs to this element. 71 * 72 * @param def The element definition object that produced and constrains this element. 73 */ setElemDef(XSLTElementDef def)74 void setElemDef(XSLTElementDef def) 75 { 76 m_elemDef = def; 77 } 78 79 /** 80 * Resolve an external entity. 81 * 82 * 83 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 84 * @param publicId The public identifer, or null if none is 85 * available. 86 * @param systemId The system identifier provided in the XML 87 * document. 88 * @return The new input source, or null to require the 89 * default behaviour. 90 */ resolveEntity( StylesheetHandler handler, String publicId, String systemId)91 public InputSource resolveEntity( 92 StylesheetHandler handler, String publicId, String systemId) 93 throws org.xml.sax.SAXException 94 { 95 return null; 96 } 97 98 /** 99 * Receive notification of a notation declaration. 100 * 101 * 102 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 103 * @param name The notation name. 104 * @param publicId The notation public identifier, or null if not 105 * available. 106 * @param systemId The notation system identifier. 107 * @see org.xml.sax.DTDHandler#notationDecl 108 */ notationDecl(StylesheetHandler handler, String name, String publicId, String systemId)109 public void notationDecl(StylesheetHandler handler, String name, 110 String publicId, String systemId) 111 { 112 113 // no op 114 } 115 116 /** 117 * Receive notification of an unparsed entity declaration. 118 * 119 * 120 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 121 * @param name The entity name. 122 * @param publicId The entity public identifier, or null if not 123 * available. 124 * @param systemId The entity system identifier. 125 * @param notationName The name of the associated notation. 126 * @see org.xml.sax.DTDHandler#unparsedEntityDecl 127 */ unparsedEntityDecl(StylesheetHandler handler, String name, String publicId, String systemId, String notationName)128 public void unparsedEntityDecl(StylesheetHandler handler, String name, 129 String publicId, String systemId, 130 String notationName) 131 { 132 133 // no op 134 } 135 136 /** 137 * Receive notification of the start of the non-text event. This 138 * is sent to the current processor when any non-text event occurs. 139 * 140 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 141 */ startNonText(StylesheetHandler handler)142 public void startNonText(StylesheetHandler handler) throws org.xml.sax.SAXException 143 { 144 145 // no op 146 } 147 148 /** 149 * Receive notification of the start of an element. 150 * 151 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 152 * @param uri The Namespace URI, or an empty string. 153 * @param localName The local name (without prefix), or empty string if not namespace processing. 154 * @param rawName The qualified name (with prefix). 155 * @param attributes The specified or defaulted attributes. 156 */ startElement( StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)157 public void startElement( 158 StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) 159 throws org.xml.sax.SAXException 160 { 161 162 if (m_savedLastOrder == null) 163 m_savedLastOrder = new IntStack(); 164 m_savedLastOrder.push(getElemDef().getLastOrder()); 165 getElemDef().setLastOrder(-1); 166 } 167 168 /** 169 * Receive notification of the end of an element. 170 * 171 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 172 * @param uri The Namespace URI, or an empty string. 173 * @param localName The local name (without prefix), or empty string if not namespace processing. 174 * @param rawName The qualified name (with prefix). 175 */ endElement( StylesheetHandler handler, String uri, String localName, String rawName)176 public void endElement( 177 StylesheetHandler handler, String uri, String localName, String rawName) 178 throws org.xml.sax.SAXException 179 { 180 if (m_savedLastOrder != null && !m_savedLastOrder.empty()) 181 getElemDef().setLastOrder(m_savedLastOrder.pop()); 182 183 if (!getElemDef().getRequiredFound()) 184 handler.error(XSLTErrorResources.ER_REQUIRED_ELEM_NOT_FOUND, new Object[]{getElemDef().getRequiredElem()}, null); 185 } 186 187 /** 188 * Receive notification of character data inside an element. 189 * 190 * 191 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 192 * @param ch The characters. 193 * @param start The start position in the character array. 194 * @param length The number of characters to use from the 195 * character array. 196 */ characters( StylesheetHandler handler, char ch[], int start, int length)197 public void characters( 198 StylesheetHandler handler, char ch[], int start, int length) 199 throws org.xml.sax.SAXException 200 { 201 handler.error(XSLTErrorResources.ER_CHARS_NOT_ALLOWED, null, null);//"Characters are not allowed at this point in the document!", 202 //null); 203 } 204 205 /** 206 * Receive notification of ignorable whitespace in element content. 207 * 208 * 209 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 210 * @param ch The whitespace characters. 211 * @param start The start position in the character array. 212 * @param length The number of characters to use from the 213 * character array. 214 */ ignorableWhitespace( StylesheetHandler handler, char ch[], int start, int length)215 public void ignorableWhitespace( 216 StylesheetHandler handler, char ch[], int start, int length) 217 throws org.xml.sax.SAXException 218 { 219 220 // no op 221 } 222 223 /** 224 * Receive notification of a processing instruction. 225 * 226 * 227 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 228 * @param target The processing instruction target. 229 * @param data The processing instruction data, or null if 230 * none is supplied. 231 */ processingInstruction( StylesheetHandler handler, String target, String data)232 public void processingInstruction( 233 StylesheetHandler handler, String target, String data) 234 throws org.xml.sax.SAXException 235 { 236 237 // no op 238 } 239 240 /** 241 * Receive notification of a skipped entity. 242 * 243 * 244 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 245 * @param name The name of the skipped entity. 246 */ skippedEntity(StylesheetHandler handler, String name)247 public void skippedEntity(StylesheetHandler handler, String name) 248 throws org.xml.sax.SAXException 249 { 250 251 // no op 252 } 253 254 /** 255 * Set the properties of an object from the given attribute list. 256 * @param handler The stylesheet's Content handler, needed for 257 * error reporting. 258 * @param rawName The raw name of the owner element, needed for 259 * error reporting. 260 * @param attributes The list of attributes. 261 * @param target The target element where the properties will be set. 262 */ setPropertiesFromAttributes( StylesheetHandler handler, String rawName, Attributes attributes, ElemTemplateElement target)263 void setPropertiesFromAttributes( 264 StylesheetHandler handler, String rawName, Attributes attributes, 265 ElemTemplateElement target) 266 throws org.xml.sax.SAXException 267 { 268 setPropertiesFromAttributes(handler, rawName, attributes, target, true); 269 } 270 271 /** 272 * Set the properties of an object from the given attribute list. 273 * @param handler The stylesheet's Content handler, needed for 274 * error reporting. 275 * @param rawName The raw name of the owner element, needed for 276 * error reporting. 277 * @param attributes The list of attributes. 278 * @param target The target element where the properties will be set. 279 * @param throwError True if it should throw an error if an 280 * attribute is not defined. 281 * @return the attributes not allowed on this element. 282 * 283 * @throws TransformerException 284 */ setPropertiesFromAttributes( StylesheetHandler handler, String rawName, Attributes attributes, ElemTemplateElement target, boolean throwError)285 Attributes setPropertiesFromAttributes( 286 StylesheetHandler handler, String rawName, Attributes attributes, 287 ElemTemplateElement target, boolean throwError) 288 throws org.xml.sax.SAXException 289 { 290 291 XSLTElementDef def = getElemDef(); 292 AttributesImpl undefines = null; 293 boolean isCompatibleMode = ((null != handler.getStylesheet() 294 && handler.getStylesheet().getCompatibleMode()) 295 || !throwError); 296 if (isCompatibleMode) 297 undefines = new AttributesImpl(); 298 299 300 // Keep track of which XSLTAttributeDefs have been processed, so 301 // I can see which default values need to be set. 302 List processedDefs = new ArrayList(); 303 304 // Keep track of XSLTAttributeDefs that were invalid 305 List errorDefs = new ArrayList(); 306 int nAttrs = attributes.getLength(); 307 308 for (int i = 0; i < nAttrs; i++) 309 { 310 String attrUri = attributes.getURI(i); 311 // Hack for Crimson. -sb 312 if((null != attrUri) && (attrUri.length() == 0) 313 && (attributes.getQName(i).startsWith("xmlns:") || 314 attributes.getQName(i).equals("xmlns"))) 315 { 316 attrUri = org.apache.xalan.templates.Constants.S_XMLNAMESPACEURI; 317 } 318 String attrLocalName = attributes.getLocalName(i); 319 XSLTAttributeDef attrDef = def.getAttributeDef(attrUri, attrLocalName); 320 321 if (null == attrDef) 322 { 323 if (!isCompatibleMode) 324 { 325 326 // Then barf, because this element does not allow this attribute. 327 handler.error(XSLTErrorResources.ER_ATTR_NOT_ALLOWED, new Object[]{attributes.getQName(i), rawName}, null);//"\""+attributes.getQName(i)+"\"" 328 //+ " attribute is not allowed on the " + rawName 329 // + " element!", null); 330 } 331 else 332 { 333 undefines.addAttribute(attrUri, attrLocalName, 334 attributes.getQName(i), 335 attributes.getType(i), 336 attributes.getValue(i)); 337 } 338 } 339 else 340 { 341 // Can we switch the order here: 342 343 boolean success = attrDef.setAttrValue(handler, attrUri, attrLocalName, 344 attributes.getQName(i), attributes.getValue(i), 345 target); 346 347 // Now we only add the element if it passed a validation check 348 if (success) 349 processedDefs.add(attrDef); 350 else 351 errorDefs.add(attrDef); 352 } 353 } 354 355 XSLTAttributeDef[] attrDefs = def.getAttributes(); 356 int nAttrDefs = attrDefs.length; 357 358 for (int i = 0; i < nAttrDefs; i++) 359 { 360 XSLTAttributeDef attrDef = attrDefs[i]; 361 String defVal = attrDef.getDefault(); 362 363 if (null != defVal) 364 { 365 if (!processedDefs.contains(attrDef)) 366 { 367 attrDef.setDefAttrValue(handler, target); 368 } 369 } 370 371 if (attrDef.getRequired()) 372 { 373 if ((!processedDefs.contains(attrDef)) && (!errorDefs.contains(attrDef))) 374 handler.error( 375 XSLMessages.createMessage( 376 XSLTErrorResources.ER_REQUIRES_ATTRIB, new Object[]{ rawName, 377 attrDef.getName() }), null); 378 } 379 } 380 381 return undefines; 382 } 383 } 384