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: ProcessorExsltFunction.java 468640 2006-10-28 06:53:53Z minchau $ 020 */ 021 package org.apache.xalan.processor; 022 023 import org.apache.xalan.templates.ElemApplyImport; 024 import org.apache.xalan.templates.ElemApplyTemplates; 025 import org.apache.xalan.templates.ElemAttribute; 026 import org.apache.xalan.templates.ElemCallTemplate; 027 import org.apache.xalan.templates.ElemComment; 028 import org.apache.xalan.templates.ElemCopy; 029 import org.apache.xalan.templates.ElemCopyOf; 030 import org.apache.xalan.templates.ElemElement; 031 import org.apache.xalan.templates.ElemExsltFuncResult; 032 import org.apache.xalan.templates.ElemExsltFunction; 033 import org.apache.xalan.templates.ElemFallback; 034 import org.apache.xalan.templates.ElemLiteralResult; 035 import org.apache.xalan.templates.ElemMessage; 036 import org.apache.xalan.templates.ElemNumber; 037 import org.apache.xalan.templates.ElemPI; 038 import org.apache.xalan.templates.ElemParam; 039 import org.apache.xalan.templates.ElemTemplate; 040 import org.apache.xalan.templates.ElemTemplateElement; 041 import org.apache.xalan.templates.ElemText; 042 import org.apache.xalan.templates.ElemTextLiteral; 043 import org.apache.xalan.templates.ElemValueOf; 044 import org.apache.xalan.templates.ElemVariable; 045 import org.apache.xalan.templates.Stylesheet; 046 import org.xml.sax.Attributes; 047 import org.xml.sax.SAXException; 048 049 050 /** 051 * This class processes parse events for an exslt func:function element. 052 * @xsl.usage internal 053 */ 054 public class ProcessorExsltFunction extends ProcessorTemplateElem 055 { 056 static final long serialVersionUID = 2411427965578315332L; 057 /** 058 * Start an ElemExsltFunction. Verify that it is top level and that it has a name attribute with a 059 * namespace. 060 */ 061 public void startElement( 062 StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) 063 throws SAXException 064 { 065 //System.out.println("ProcessorFunction.startElement()"); 066 String msg = ""; 067 if (!(handler.getElemTemplateElement() instanceof Stylesheet)) 068 { 069 msg = "func:function element must be top level."; 070 handler.error(msg, new SAXException(msg)); 071 } 072 super.startElement(handler, uri, localName, rawName, attributes); 073 074 String val = attributes.getValue("name"); 075 int indexOfColon = val.indexOf(":"); 076 if (indexOfColon > 0) 077 { 078 //String prefix = val.substring(0, indexOfColon); 079 //String localVal = val.substring(indexOfColon + 1); 080 //String ns = handler.getNamespaceSupport().getURI(prefix); 081 //if (ns.length() > 0) 082 // System.out.println("fullfuncname " + ns + localVal); 083 } 084 else 085 { 086 msg = "func:function name must have namespace"; 087 handler.error(msg, new SAXException(msg)); 088 } 089 } 090 091 /** 092 * Must include; super doesn't suffice! 093 */ 094 protected void appendAndPush( 095 StylesheetHandler handler, ElemTemplateElement elem) 096 throws SAXException 097 { 098 //System.out.println("ProcessorFunction appendAndPush()" + elem); 099 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 */ 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 */ 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 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 }