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: XSLTElementProcessor.java 1225754 2011-12-30 05:31:15Z mrglavas $ 020 */ 021 package org.apache.xalan.processor; 022 023 import java.util.ArrayList; 024 import java.util.List; 025 026 import javax.xml.transform.TransformerException; 027 028 import org.apache.xalan.res.XSLMessages; 029 import org.apache.xalan.res.XSLTErrorResources; 030 import org.apache.xalan.templates.ElemTemplateElement; 031 import org.apache.xml.utils.IntStack; 032 import org.xml.sax.Attributes; 033 import org.xml.sax.InputSource; 034 import org.xml.sax.helpers.AttributesImpl; 035 036 /** 037 * This class acts as the superclass for all stylesheet element 038 * processors, and deals with things that are common to all elements. 039 * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a> 040 */ 041 public class XSLTElementProcessor extends ElemTemplateElement 042 { 043 static final long serialVersionUID = 5597421564955304421L; 044 045 /** 046 * Construct a processor for top-level elements. 047 * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a> 048 */ 049 XSLTElementProcessor(){} 050 051 private IntStack m_savedLastOrder; 052 053 /** 054 * The element definition that this processor conforms to. 055 */ 056 private XSLTElementDef m_elemDef; 057 058 /** 059 * Get the element definition that belongs to this element. 060 * 061 * @return The element definition object that produced and constrains this element. 062 */ 063 XSLTElementDef getElemDef() 064 { 065 return m_elemDef; 066 } 067 068 /** 069 * Set the element definition that belongs to this element. 070 * 071 * @param def The element definition object that produced and constrains this element. 072 */ 073 void setElemDef(XSLTElementDef def) 074 { 075 m_elemDef = def; 076 } 077 078 /** 079 * Resolve an external entity. 080 * 081 * 082 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 083 * @param publicId The public identifer, or null if none is 084 * available. 085 * @param systemId The system identifier provided in the XML 086 * document. 087 * @return The new input source, or null to require the 088 * default behaviour. 089 */ 090 public InputSource resolveEntity( 091 StylesheetHandler handler, String publicId, String systemId) 092 throws org.xml.sax.SAXException 093 { 094 return null; 095 } 096 097 /** 098 * Receive notification of a notation declaration. 099 * 100 * 101 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 102 * @param name The notation name. 103 * @param publicId The notation public identifier, or null if not 104 * available. 105 * @param systemId The notation system identifier. 106 * @see org.xml.sax.DTDHandler#notationDecl 107 */ 108 public void notationDecl(StylesheetHandler handler, String name, 109 String publicId, String systemId) 110 { 111 112 // no op 113 } 114 115 /** 116 * Receive notification of an unparsed entity declaration. 117 * 118 * 119 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 120 * @param name The entity name. 121 * @param publicId The entity public identifier, or null if not 122 * available. 123 * @param systemId The entity system identifier. 124 * @param notationName The name of the associated notation. 125 * @see org.xml.sax.DTDHandler#unparsedEntityDecl 126 */ 127 public void unparsedEntityDecl(StylesheetHandler handler, String name, 128 String publicId, String systemId, 129 String notationName) 130 { 131 132 // no op 133 } 134 135 /** 136 * Receive notification of the start of the non-text event. This 137 * is sent to the current processor when any non-text event occurs. 138 * 139 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 140 */ 141 public void startNonText(StylesheetHandler handler) throws org.xml.sax.SAXException 142 { 143 144 // no op 145 } 146 147 /** 148 * Receive notification of the start of an element. 149 * 150 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 151 * @param uri The Namespace URI, or an empty string. 152 * @param localName The local name (without prefix), or empty string if not namespace processing. 153 * @param rawName The qualified name (with prefix). 154 * @param attributes The specified or defaulted attributes. 155 */ 156 public void startElement( 157 StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) 158 throws org.xml.sax.SAXException 159 { 160 161 if (m_savedLastOrder == null) 162 m_savedLastOrder = new IntStack(); 163 m_savedLastOrder.push(getElemDef().getLastOrder()); 164 getElemDef().setLastOrder(-1); 165 } 166 167 /** 168 * Receive notification of the end of an element. 169 * 170 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 171 * @param uri The Namespace URI, or an empty string. 172 * @param localName The local name (without prefix), or empty string if not namespace processing. 173 * @param rawName The qualified name (with prefix). 174 */ 175 public void endElement( 176 StylesheetHandler handler, String uri, String localName, String rawName) 177 throws org.xml.sax.SAXException 178 { 179 if (m_savedLastOrder != null && !m_savedLastOrder.empty()) 180 getElemDef().setLastOrder(m_savedLastOrder.pop()); 181 182 if (!getElemDef().getRequiredFound()) 183 handler.error(XSLTErrorResources.ER_REQUIRED_ELEM_NOT_FOUND, new Object[]{getElemDef().getRequiredElem()}, null); 184 } 185 186 /** 187 * Receive notification of character data inside an element. 188 * 189 * 190 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 191 * @param ch The characters. 192 * @param start The start position in the character array. 193 * @param length The number of characters to use from the 194 * character array. 195 */ 196 public void characters( 197 StylesheetHandler handler, char ch[], int start, int length) 198 throws org.xml.sax.SAXException 199 { 200 handler.error(XSLTErrorResources.ER_CHARS_NOT_ALLOWED, null, null);//"Characters are not allowed at this point in the document!", 201 //null); 202 } 203 204 /** 205 * Receive notification of ignorable whitespace in element content. 206 * 207 * 208 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 209 * @param ch The whitespace characters. 210 * @param start The start position in the character array. 211 * @param length The number of characters to use from the 212 * character array. 213 */ 214 public void ignorableWhitespace( 215 StylesheetHandler handler, char ch[], int start, int length) 216 throws org.xml.sax.SAXException 217 { 218 219 // no op 220 } 221 222 /** 223 * Receive notification of a processing instruction. 224 * 225 * 226 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 227 * @param target The processing instruction target. 228 * @param data The processing instruction data, or null if 229 * none is supplied. 230 */ 231 public void processingInstruction( 232 StylesheetHandler handler, String target, String data) 233 throws org.xml.sax.SAXException 234 { 235 236 // no op 237 } 238 239 /** 240 * Receive notification of a skipped entity. 241 * 242 * 243 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 244 * @param name The name of the skipped entity. 245 */ 246 public void skippedEntity(StylesheetHandler handler, String name) 247 throws org.xml.sax.SAXException 248 { 249 250 // no op 251 } 252 253 /** 254 * Set the properties of an object from the given attribute list. 255 * @param handler The stylesheet's Content handler, needed for 256 * error reporting. 257 * @param rawName The raw name of the owner element, needed for 258 * error reporting. 259 * @param attributes The list of attributes. 260 * @param target The target element where the properties will be set. 261 */ 262 void setPropertiesFromAttributes( 263 StylesheetHandler handler, String rawName, Attributes attributes, 264 ElemTemplateElement target) 265 throws org.xml.sax.SAXException 266 { 267 setPropertiesFromAttributes(handler, rawName, attributes, target, true); 268 } 269 270 /** 271 * Set the properties of an object from the given attribute list. 272 * @param handler The stylesheet's Content handler, needed for 273 * error reporting. 274 * @param rawName The raw name of the owner element, needed for 275 * error reporting. 276 * @param attributes The list of attributes. 277 * @param target The target element where the properties will be set. 278 * @param throwError True if it should throw an error if an 279 * attribute is not defined. 280 * @return the attributes not allowed on this element. 281 * 282 * @throws TransformerException 283 */ 284 Attributes setPropertiesFromAttributes( 285 StylesheetHandler handler, String rawName, Attributes attributes, 286 ElemTemplateElement target, boolean throwError) 287 throws org.xml.sax.SAXException 288 { 289 290 XSLTElementDef def = getElemDef(); 291 AttributesImpl undefines = null; 292 boolean isCompatibleMode = ((null != handler.getStylesheet() 293 && handler.getStylesheet().getCompatibleMode()) 294 || !throwError); 295 if (isCompatibleMode) 296 undefines = new AttributesImpl(); 297 298 299 // Keep track of which XSLTAttributeDefs have been processed, so 300 // I can see which default values need to be set. 301 List processedDefs = new ArrayList(); 302 303 // Keep track of XSLTAttributeDefs that were invalid 304 List errorDefs = new ArrayList(); 305 int nAttrs = attributes.getLength(); 306 307 for (int i = 0; i < nAttrs; i++) 308 { 309 String attrUri = attributes.getURI(i); 310 // Hack for Crimson. -sb 311 if((null != attrUri) && (attrUri.length() == 0) 312 && (attributes.getQName(i).startsWith("xmlns:") || 313 attributes.getQName(i).equals("xmlns"))) 314 { 315 attrUri = org.apache.xalan.templates.Constants.S_XMLNAMESPACEURI; 316 } 317 String attrLocalName = attributes.getLocalName(i); 318 XSLTAttributeDef attrDef = def.getAttributeDef(attrUri, attrLocalName); 319 320 if (null == attrDef) 321 { 322 if (!isCompatibleMode) 323 { 324 325 // Then barf, because this element does not allow this attribute. 326 handler.error(XSLTErrorResources.ER_ATTR_NOT_ALLOWED, new Object[]{attributes.getQName(i), rawName}, null);//"\""+attributes.getQName(i)+"\"" 327 //+ " attribute is not allowed on the " + rawName 328 // + " element!", null); 329 } 330 else 331 { 332 undefines.addAttribute(attrUri, attrLocalName, 333 attributes.getQName(i), 334 attributes.getType(i), 335 attributes.getValue(i)); 336 } 337 } 338 else 339 { 340 // Can we switch the order here: 341 342 boolean success = attrDef.setAttrValue(handler, attrUri, attrLocalName, 343 attributes.getQName(i), attributes.getValue(i), 344 target); 345 346 // Now we only add the element if it passed a validation check 347 if (success) 348 processedDefs.add(attrDef); 349 else 350 errorDefs.add(attrDef); 351 } 352 } 353 354 XSLTAttributeDef[] attrDefs = def.getAttributes(); 355 int nAttrDefs = attrDefs.length; 356 357 for (int i = 0; i < nAttrDefs; i++) 358 { 359 XSLTAttributeDef attrDef = attrDefs[i]; 360 String defVal = attrDef.getDefault(); 361 362 if (null != defVal) 363 { 364 if (!processedDefs.contains(attrDef)) 365 { 366 attrDef.setDefAttrValue(handler, target); 367 } 368 } 369 370 if (attrDef.getRequired()) 371 { 372 if ((!processedDefs.contains(attrDef)) && (!errorDefs.contains(attrDef))) 373 handler.error( 374 XSLMessages.createMessage( 375 XSLTErrorResources.ER_REQUIRES_ATTRIB, new Object[]{ rawName, 376 attrDef.getName() }), null); 377 } 378 } 379 380 return undefines; 381 } 382 }