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: ProcessorLRE.java 475981 2006-11-16 23:35:53Z minchau $ 20 */ 21 package org.apache.xalan.processor; 22 23 import java.util.List; 24 25 import javax.xml.transform.TransformerConfigurationException; 26 import javax.xml.transform.TransformerException; 27 28 import org.apache.xalan.res.XSLMessages; 29 import org.apache.xalan.res.XSLTErrorResources; 30 import org.apache.xalan.templates.Constants; 31 import org.apache.xalan.templates.ElemExtensionCall; 32 import org.apache.xalan.templates.ElemLiteralResult; 33 import org.apache.xalan.templates.ElemTemplate; 34 import org.apache.xalan.templates.ElemTemplateElement; 35 import org.apache.xalan.templates.Stylesheet; 36 import org.apache.xalan.templates.StylesheetRoot; 37 import org.apache.xalan.templates.XMLNSDecl; 38 import org.apache.xml.utils.SAXSourceLocator; 39 import org.apache.xpath.XPath; 40 41 import org.xml.sax.Attributes; 42 import org.xml.sax.Locator; 43 import org.xml.sax.helpers.AttributesImpl; 44 45 /** 46 * Processes an XSLT literal-result-element, or something that looks 47 * like one. The actual {@link org.apache.xalan.templates.ElemTemplateElement} 48 * produced may be a {@link org.apache.xalan.templates.ElemLiteralResult}, 49 * a {@link org.apache.xalan.templates.StylesheetRoot}, or a 50 * {@link org.apache.xalan.templates.ElemExtensionCall}. 51 * 52 * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a> 53 * @see org.apache.xalan.templates.ElemLiteralResult 54 * @xsl.usage internal 55 */ 56 public class ProcessorLRE extends ProcessorTemplateElem 57 { 58 static final long serialVersionUID = -1490218021772101404L; 59 /** 60 * Receive notification of the start of an element. 61 * 62 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 63 * @param uri The Namespace URI, or an empty string. 64 * @param localName The local name (without prefix), or empty string if not namespace processing. 65 * @param rawName The qualified name (with prefix). 66 * @param attributes The specified or defaulted attributes. 67 */ startElement( StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)68 public void startElement( 69 StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) 70 throws org.xml.sax.SAXException 71 { 72 73 try 74 { 75 ElemTemplateElement p = handler.getElemTemplateElement(); 76 boolean excludeXSLDecl = false; 77 boolean isLREAsStyleSheet = false; 78 79 if (null == p) 80 { 81 82 // Literal Result Template as stylesheet. 83 XSLTElementProcessor lreProcessor = handler.popProcessor(); 84 XSLTElementProcessor stylesheetProcessor = 85 handler.getProcessorFor(Constants.S_XSLNAMESPACEURL, "stylesheet", 86 "xsl:stylesheet"); 87 88 handler.pushProcessor(lreProcessor); 89 90 Stylesheet stylesheet; 91 try 92 { 93 stylesheet = getStylesheetRoot(handler); 94 } 95 catch(TransformerConfigurationException tfe) 96 { 97 throw new TransformerException(tfe); 98 } 99 100 // stylesheet.setDOMBackPointer(handler.getOriginatingNode()); 101 // ***** Note that we're assigning an empty locator. Is this necessary? 102 SAXSourceLocator slocator = new SAXSourceLocator(); 103 Locator locator = handler.getLocator(); 104 if(null != locator) 105 { 106 slocator.setLineNumber(locator.getLineNumber()); 107 slocator.setColumnNumber(locator.getColumnNumber()); 108 slocator.setPublicId(locator.getPublicId()); 109 slocator.setSystemId(locator.getSystemId()); 110 } 111 stylesheet.setLocaterInfo(slocator); 112 stylesheet.setPrefixes(handler.getNamespaceSupport()); 113 handler.pushStylesheet(stylesheet); 114 115 isLREAsStyleSheet = true; 116 117 AttributesImpl stylesheetAttrs = new AttributesImpl(); 118 AttributesImpl lreAttrs = new AttributesImpl(); 119 int n = attributes.getLength(); 120 121 for (int i = 0; i < n; i++) 122 { 123 String attrLocalName = attributes.getLocalName(i); 124 String attrUri = attributes.getURI(i); 125 String value = attributes.getValue(i); 126 127 if ((null != attrUri) && attrUri.equals(Constants.S_XSLNAMESPACEURL)) 128 { 129 stylesheetAttrs.addAttribute(null, attrLocalName, attrLocalName, 130 attributes.getType(i), 131 attributes.getValue(i)); 132 } 133 else if ((attrLocalName.startsWith("xmlns:") || attrLocalName.equals( 134 "xmlns")) && value.equals(Constants.S_XSLNAMESPACEURL)) 135 { 136 137 // ignore 138 } 139 else 140 { 141 lreAttrs.addAttribute(attrUri, attrLocalName, 142 attributes.getQName(i), 143 attributes.getType(i), 144 attributes.getValue(i)); 145 } 146 } 147 148 attributes = lreAttrs; 149 150 // Set properties from the attributes, but don't throw 151 // an error if there is an attribute defined that is not 152 // allowed on a stylesheet. 153 try{ 154 stylesheetProcessor.setPropertiesFromAttributes(handler, "stylesheet", 155 stylesheetAttrs, stylesheet); 156 } 157 catch (Exception e) 158 { 159 // This is pretty ugly, but it will have to do for now. 160 // This is just trying to append some text specifying that 161 // this error came from a missing or invalid XSLT namespace 162 // declaration. 163 // If someone comes up with a better solution, please feel 164 // free to contribute it. -mm 165 166 if (stylesheet.getDeclaredPrefixes() == null || 167 !declaredXSLNS(stylesheet)) 168 { 169 throw new org.xml.sax.SAXException(XSLMessages.createWarning(XSLTErrorResources.WG_OLD_XSLT_NS, null)); 170 } 171 else 172 { 173 throw new org.xml.sax.SAXException(e); 174 } 175 } 176 handler.pushElemTemplateElement(stylesheet); 177 178 ElemTemplate template = new ElemTemplate(); 179 if (slocator != null) 180 template.setLocaterInfo(slocator); 181 182 appendAndPush(handler, template); 183 184 XPath rootMatch = new XPath("/", stylesheet, stylesheet, XPath.MATCH, 185 handler.getStylesheetProcessor().getErrorListener()); 186 187 template.setMatch(rootMatch); 188 189 // template.setDOMBackPointer(handler.getOriginatingNode()); 190 stylesheet.setTemplate(template); 191 192 p = handler.getElemTemplateElement(); 193 excludeXSLDecl = true; 194 } 195 196 XSLTElementDef def = getElemDef(); 197 Class classObject = def.getClassObject(); 198 boolean isExtension = false; 199 boolean isComponentDecl = false; 200 boolean isUnknownTopLevel = false; 201 202 while (null != p) 203 { 204 205 // System.out.println("Checking: "+p); 206 if (p instanceof ElemLiteralResult) 207 { 208 ElemLiteralResult parentElem = (ElemLiteralResult) p; 209 210 isExtension = parentElem.containsExtensionElementURI(uri); 211 } 212 else if (p instanceof Stylesheet) 213 { 214 Stylesheet parentElem = (Stylesheet) p; 215 216 isExtension = parentElem.containsExtensionElementURI(uri); 217 218 if ((false == isExtension) && (null != uri) 219 && (uri.equals(Constants.S_BUILTIN_EXTENSIONS_URL) 220 || uri.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL))) 221 { 222 isComponentDecl = true; 223 } 224 else 225 { 226 isUnknownTopLevel = true; 227 } 228 } 229 230 if (isExtension) 231 break; 232 233 p = p.getParentElem(); 234 } 235 236 ElemTemplateElement elem = null; 237 238 try 239 { 240 if (isExtension) 241 { 242 243 // System.out.println("Creating extension(1): "+uri); 244 elem = new ElemExtensionCall(); 245 } 246 else if (isComponentDecl) 247 { 248 elem = (ElemTemplateElement) classObject.newInstance(); 249 } 250 else if (isUnknownTopLevel) 251 { 252 253 // TBD: Investigate, not sure about this. -sb 254 elem = (ElemTemplateElement) classObject.newInstance(); 255 } 256 else 257 { 258 elem = (ElemTemplateElement) classObject.newInstance(); 259 } 260 261 elem.setDOMBackPointer(handler.getOriginatingNode()); 262 elem.setLocaterInfo(handler.getLocator()); 263 elem.setPrefixes(handler.getNamespaceSupport(), excludeXSLDecl); 264 265 if (elem instanceof ElemLiteralResult) 266 { 267 ((ElemLiteralResult) elem).setNamespace(uri); 268 ((ElemLiteralResult) elem).setLocalName(localName); 269 ((ElemLiteralResult) elem).setRawName(rawName); 270 ((ElemLiteralResult) elem).setIsLiteralResultAsStylesheet( 271 isLREAsStyleSheet); 272 } 273 } 274 catch (InstantiationException ie) 275 { 276 handler.error(XSLTErrorResources.ER_FAILED_CREATING_ELEMLITRSLT, null, ie);//"Failed creating ElemLiteralResult instance!", ie); 277 } 278 catch (IllegalAccessException iae) 279 { 280 handler.error(XSLTErrorResources.ER_FAILED_CREATING_ELEMLITRSLT, null, iae);//"Failed creating ElemLiteralResult instance!", iae); 281 } 282 283 setPropertiesFromAttributes(handler, rawName, attributes, elem); 284 285 // bit of a hack here... 286 if (!isExtension && (elem instanceof ElemLiteralResult)) 287 { 288 isExtension = 289 ((ElemLiteralResult) elem).containsExtensionElementURI(uri); 290 291 if (isExtension) 292 { 293 294 // System.out.println("Creating extension(2): "+uri); 295 elem = new ElemExtensionCall(); 296 297 elem.setLocaterInfo(handler.getLocator()); 298 elem.setPrefixes(handler.getNamespaceSupport()); 299 ((ElemLiteralResult) elem).setNamespace(uri); 300 ((ElemLiteralResult) elem).setLocalName(localName); 301 ((ElemLiteralResult) elem).setRawName(rawName); 302 setPropertiesFromAttributes(handler, rawName, attributes, elem); 303 } 304 } 305 306 appendAndPush(handler, elem); 307 } 308 catch(TransformerException te) 309 { 310 throw new org.xml.sax.SAXException(te); 311 } 312 } 313 314 /** 315 * This method could be over-ridden by a class that extends this class. 316 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 317 * @return an object that represents the stylesheet element. 318 */ getStylesheetRoot(StylesheetHandler handler)319 protected Stylesheet getStylesheetRoot(StylesheetHandler handler) throws TransformerConfigurationException 320 { 321 StylesheetRoot stylesheet; 322 stylesheet = new StylesheetRoot(handler.getSchema(), handler.getStylesheetProcessor().getErrorListener()); 323 if (handler.getStylesheetProcessor().isSecureProcessing()) 324 stylesheet.setSecureProcessing(true); 325 326 return stylesheet; 327 } 328 329 330 /** 331 * Receive notification of the end of an element. 332 * 333 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 334 * @param uri The Namespace URI, or an empty string. 335 * @param localName The local name (without prefix), or empty string if not namespace processing. 336 * @param rawName The qualified name (with prefix). 337 */ endElement( StylesheetHandler handler, String uri, String localName, String rawName)338 public void endElement( 339 StylesheetHandler handler, String uri, String localName, String rawName) 340 throws org.xml.sax.SAXException 341 { 342 343 ElemTemplateElement elem = handler.getElemTemplateElement(); 344 345 if (elem instanceof ElemLiteralResult) 346 { 347 if (((ElemLiteralResult) elem).getIsLiteralResultAsStylesheet()) 348 { 349 handler.popStylesheet(); 350 } 351 } 352 353 super.endElement(handler, uri, localName, rawName); 354 } 355 declaredXSLNS(Stylesheet stylesheet)356 private boolean declaredXSLNS(Stylesheet stylesheet) 357 { 358 List declaredPrefixes = stylesheet.getDeclaredPrefixes(); 359 int n = declaredPrefixes.size(); 360 361 for (int i = 0; i < n; i++) 362 { 363 XMLNSDecl decl = (XMLNSDecl) declaredPrefixes.get(i); 364 if(decl.getURI().equals(Constants.S_XSLNAMESPACEURL)) 365 return true; 366 } 367 return false; 368 } 369 } 370