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: ProcessorLRE.java 475981 2006-11-16 23:35:53Z minchau $ 020 */ 021 package org.apache.xalan.processor; 022 023 import java.util.List; 024 025 import javax.xml.transform.TransformerConfigurationException; 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.Constants; 031 import org.apache.xalan.templates.ElemExtensionCall; 032 import org.apache.xalan.templates.ElemLiteralResult; 033 import org.apache.xalan.templates.ElemTemplate; 034 import org.apache.xalan.templates.ElemTemplateElement; 035 import org.apache.xalan.templates.Stylesheet; 036 import org.apache.xalan.templates.StylesheetRoot; 037 import org.apache.xalan.templates.XMLNSDecl; 038 import org.apache.xml.utils.SAXSourceLocator; 039 import org.apache.xpath.XPath; 040 041 import org.xml.sax.Attributes; 042 import org.xml.sax.Locator; 043 import org.xml.sax.helpers.AttributesImpl; 044 045 /** 046 * Processes an XSLT literal-result-element, or something that looks 047 * like one. The actual {@link org.apache.xalan.templates.ElemTemplateElement} 048 * produced may be a {@link org.apache.xalan.templates.ElemLiteralResult}, 049 * a {@link org.apache.xalan.templates.StylesheetRoot}, or a 050 * {@link org.apache.xalan.templates.ElemExtensionCall}. 051 * 052 * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a> 053 * @see org.apache.xalan.templates.ElemLiteralResult 054 * @xsl.usage internal 055 */ 056 public class ProcessorLRE extends ProcessorTemplateElem 057 { 058 static final long serialVersionUID = -1490218021772101404L; 059 /** 060 * Receive notification of the start of an element. 061 * 062 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. 063 * @param uri The Namespace URI, or an empty string. 064 * @param localName The local name (without prefix), or empty string if not namespace processing. 065 * @param rawName The qualified name (with prefix). 066 * @param attributes The specified or defaulted attributes. 067 */ 068 public void startElement( 069 StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) 070 throws org.xml.sax.SAXException 071 { 072 073 try 074 { 075 ElemTemplateElement p = handler.getElemTemplateElement(); 076 boolean excludeXSLDecl = false; 077 boolean isLREAsStyleSheet = false; 078 079 if (null == p) 080 { 081 082 // Literal Result Template as stylesheet. 083 XSLTElementProcessor lreProcessor = handler.popProcessor(); 084 XSLTElementProcessor stylesheetProcessor = 085 handler.getProcessorFor(Constants.S_XSLNAMESPACEURL, "stylesheet", 086 "xsl:stylesheet"); 087 088 handler.pushProcessor(lreProcessor); 089 090 Stylesheet stylesheet; 091 try 092 { 093 stylesheet = getStylesheetRoot(handler); 094 } 095 catch(TransformerConfigurationException tfe) 096 { 097 throw new TransformerException(tfe); 098 } 099 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 */ 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 */ 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 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 }