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: ProcessorExsltFunction.java 468640 2006-10-28 06:53:53Z minchau $ 20 */ 21 package org.apache.xalan.processor; 22 23 import org.apache.xalan.templates.ElemApplyImport; 24 import org.apache.xalan.templates.ElemApplyTemplates; 25 import org.apache.xalan.templates.ElemAttribute; 26 import org.apache.xalan.templates.ElemCallTemplate; 27 import org.apache.xalan.templates.ElemComment; 28 import org.apache.xalan.templates.ElemCopy; 29 import org.apache.xalan.templates.ElemCopyOf; 30 import org.apache.xalan.templates.ElemElement; 31 import org.apache.xalan.templates.ElemExsltFuncResult; 32 import org.apache.xalan.templates.ElemExsltFunction; 33 import org.apache.xalan.templates.ElemFallback; 34 import org.apache.xalan.templates.ElemLiteralResult; 35 import org.apache.xalan.templates.ElemMessage; 36 import org.apache.xalan.templates.ElemNumber; 37 import org.apache.xalan.templates.ElemPI; 38 import org.apache.xalan.templates.ElemParam; 39 import org.apache.xalan.templates.ElemTemplate; 40 import org.apache.xalan.templates.ElemTemplateElement; 41 import org.apache.xalan.templates.ElemText; 42 import org.apache.xalan.templates.ElemTextLiteral; 43 import org.apache.xalan.templates.ElemValueOf; 44 import org.apache.xalan.templates.ElemVariable; 45 import org.apache.xalan.templates.Stylesheet; 46 import org.xml.sax.Attributes; 47 import org.xml.sax.SAXException; 48 49 50 /** 51 * This class processes parse events for an exslt func:function element. 52 * @xsl.usage internal 53 */ 54 public class ProcessorExsltFunction extends ProcessorTemplateElem 55 { 56 static final long serialVersionUID = 2411427965578315332L; 57 /** 58 * Start an ElemExsltFunction. Verify that it is top level and that it has a name attribute with a 59 * namespace. 60 */ startElement( StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)61 public void startElement( 62 StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) 63 throws SAXException 64 { 65 //System.out.println("ProcessorFunction.startElement()"); 66 String msg = ""; 67 if (!(handler.getElemTemplateElement() instanceof Stylesheet)) 68 { 69 msg = "func:function element must be top level."; 70 handler.error(msg, new SAXException(msg)); 71 } 72 super.startElement(handler, uri, localName, rawName, attributes); 73 74 String val = attributes.getValue("name"); 75 int indexOfColon = val.indexOf(":"); 76 if (indexOfColon > 0) 77 { 78 //String prefix = val.substring(0, indexOfColon); 79 //String localVal = val.substring(indexOfColon + 1); 80 //String ns = handler.getNamespaceSupport().getURI(prefix); 81 //if (ns.length() > 0) 82 // System.out.println("fullfuncname " + ns + localVal); 83 } 84 else 85 { 86 msg = "func:function name must have namespace"; 87 handler.error(msg, new SAXException(msg)); 88 } 89 } 90 91 /** 92 * Must include; super doesn't suffice! 93 */ appendAndPush( StylesheetHandler handler, ElemTemplateElement elem)94 protected void appendAndPush( 95 StylesheetHandler handler, ElemTemplateElement elem) 96 throws SAXException 97 { 98 //System.out.println("ProcessorFunction appendAndPush()" + elem); 99 super.appendAndPush(handler, elem); 100 //System.out.println("originating node " + handler.getOriginatingNode()); 101 elem.setDOMBackPointer(handler.getOriginatingNode()); 102 handler.getStylesheet().setTemplate((ElemTemplate) elem); 103 } 104 105 /** 106 * End an ElemExsltFunction, and verify its validity. 107 */ endElement( StylesheetHandler handler, String uri, String localName, String rawName)108 public void endElement( 109 StylesheetHandler handler, String uri, String localName, String rawName) 110 throws SAXException 111 { 112 ElemTemplateElement function = handler.getElemTemplateElement(); 113 validate(function, handler); // may throw exception 114 super.endElement(handler, uri, localName, rawName); 115 } 116 117 /** 118 * Non-recursive traversal of FunctionElement tree based on TreeWalker to verify that 119 * there are no literal result elements except within a func:result element and that 120 * the func:result element does not contain any following siblings except xsl:fallback. 121 */ validate(ElemTemplateElement elem, StylesheetHandler handler)122 public void validate(ElemTemplateElement elem, StylesheetHandler handler) 123 throws SAXException 124 { 125 String msg = ""; 126 while (elem != null) 127 { 128 //System.out.println("elem " + elem); 129 if (elem instanceof ElemExsltFuncResult 130 && elem.getNextSiblingElem() != null 131 && !(elem.getNextSiblingElem() instanceof ElemFallback)) 132 { 133 msg = "func:result has an illegal following sibling (only xsl:fallback allowed)"; 134 handler.error(msg, new SAXException(msg)); 135 } 136 137 if((elem instanceof ElemApplyImport 138 || elem instanceof ElemApplyTemplates 139 || elem instanceof ElemAttribute 140 || elem instanceof ElemCallTemplate 141 || elem instanceof ElemComment 142 || elem instanceof ElemCopy 143 || elem instanceof ElemCopyOf 144 || elem instanceof ElemElement 145 || elem instanceof ElemLiteralResult 146 || elem instanceof ElemNumber 147 || elem instanceof ElemPI 148 || elem instanceof ElemText 149 || elem instanceof ElemTextLiteral 150 || elem instanceof ElemValueOf) 151 && !(ancestorIsOk(elem))) 152 { 153 msg ="misplaced literal result in a func:function container."; 154 handler.error(msg, new SAXException(msg)); 155 } 156 ElemTemplateElement nextElem = elem.getFirstChildElem(); 157 while (nextElem == null) 158 { 159 nextElem = elem.getNextSiblingElem(); 160 if (nextElem == null) 161 elem = elem.getParentElem(); 162 if (elem == null || elem instanceof ElemExsltFunction) 163 return; // ok 164 } 165 elem = nextElem; 166 } 167 } 168 169 /** 170 * Verify that a literal result belongs to a result element, a variable, 171 * or a parameter. 172 */ 173 ancestorIsOk(ElemTemplateElement child)174 boolean ancestorIsOk(ElemTemplateElement child) 175 { 176 while (child.getParentElem() != null && !(child.getParentElem() instanceof ElemExsltFunction)) 177 { 178 ElemTemplateElement parent = child.getParentElem(); 179 if (parent instanceof ElemExsltFuncResult 180 || parent instanceof ElemVariable 181 || parent instanceof ElemParam 182 || parent instanceof ElemMessage) 183 return true; 184 child = parent; 185 } 186 return false; 187 } 188 189 } 190