1 package com.icl.saxon.style; 2 import com.icl.saxon.tree.AttributeCollection; 3 import com.icl.saxon.tree.NodeImpl; 4 import com.icl.saxon.*; 5 import com.icl.saxon.om.*; 6 import com.icl.saxon.expr.*; 7 import javax.xml.transform.*; 8 import java.util.*; 9 import java.io.*; 10 11 14 15 public class XSLCallTemplate extends StyleElement { 16 17 private int calledTemplateFingerprint = -1; private XSLTemplate template = null; 19 private boolean useTailRecursion = false; 20 private Expression calledTemplateExpression; private String calledTemplateName = null; 23 27 28 public boolean isInstruction() { 29 return true; 30 } 31 32 36 37 public boolean doesPostProcessing() { 38 return false; 39 } 40 41 public void prepareAttributes() throws TransformerConfigurationException { 42 43 StandardNames sn = getStandardNames(); 44 AttributeCollection atts = getAttributeList(); 45 46 String allowAVTatt = null; 47 String nameAttribute = null; 48 49 for (int a=0; a<atts.getLength(); a++) { 50 int nc = atts.getNameCode(a); 51 int f = nc & 0xfffff; 52 if (f==sn.NAME) { 53 nameAttribute = atts.getValue(a); 54 } else if (f==sn.SAXON_ALLOW_AVT) { 55 allowAVTatt = atts.getValue(a); 56 } else { 57 checkUnknownAttribute(nc); 58 } 59 } 60 61 if (nameAttribute==null) { 62 reportAbsence("name"); 63 return; 64 } 65 66 boolean allowAVT = (allowAVTatt != null && allowAVTatt.equals("yes")); 67 if (allowAVT) { 68 calledTemplateExpression = makeAttributeValueTemplate(nameAttribute); 69 } else { 70 if (!Name.isQName(nameAttribute)) { 71 compileError("Name of called template must be a valid QName"); 72 } 73 calledTemplateName = nameAttribute; 74 try { 75 calledTemplateFingerprint = 76 makeNameCode(nameAttribute, false) & 0xfffff; 77 } catch (NamespaceException err) { 78 compileError(err.getMessage()); 79 } 80 } 81 } 82 83 public void validate() throws TransformerConfigurationException { 84 checkWithinTemplate(); 85 86 if (calledTemplateExpression==null) { 87 template = findTemplate(calledTemplateFingerprint); 88 89 94 if (Navigator.isAncestor(template, this)) { 95 useTailRecursion = true; 96 StyleElement n = this; 97 while (n!=template) { 98 if ((n.isInstruction() && n.getNextSibling()!=null) || 99 n.doesPostProcessing()) { 100 useTailRecursion = false; 101 break; 102 } 103 n = (StyleElement)n.getParentNode(); 104 } 105 } 107 } 108 109 } 110 111 private XSLTemplate findTemplate(int fingerprint) 112 throws TransformerConfigurationException { 113 114 XSLStyleSheet stylesheet = getPrincipalStyleSheet(); 115 Vector toplevel = stylesheet.getTopLevel(); 116 117 120 for (int i=toplevel.size()-1; i>=0; i--) { 121 if (toplevel.elementAt(i) instanceof XSLTemplate) { 122 XSLTemplate t = (XSLTemplate)toplevel.elementAt(i); 123 if (t.getTemplateFingerprint() == fingerprint) { 124 return t; 125 } 126 } 127 } 128 compileError("No template exists named " + calledTemplateName); 129 return null; 130 } 131 132 public void process(Context context) throws TransformerException 133 { 134 136 XSLTemplate target = template; 137 if (calledTemplateExpression != null) { 138 String qname = calledTemplateExpression.evaluateAsString(context); 139 if (!Name.isQName(qname)) { 140 throw styleError("Invalid template name: " + qname); 141 } 142 int fprint; 143 try { 144 fprint = makeNameCode(qname, false) & 0xfffff; 145 } catch (NamespaceException err) { 146 throw styleError(err.getMessage()); 147 } 148 target = findTemplate(fprint); 149 if (target==null) { 150 throw styleError("Template " + qname + " has not been defined"); 151 } 152 } 153 154 156 ParameterSet params = null; 157 158 if (hasChildNodes()) { 159 NodeImpl child = (NodeImpl)getFirstChild(); 160 params = new ParameterSet(); 161 while (child != null) { 162 if (child instanceof XSLWithParam) { XSLWithParam param = (XSLWithParam)child; 164 params.put(param.getVariableFingerprint(), param.getParamValue(context)); 165 } 166 child = (NodeImpl)child.getNextSibling(); 167 } 168 } 169 170 172 if (useTailRecursion) { 173 if (params==null) { params = new ParameterSet(); 175 } 176 context.setTailRecursion(params); 177 } else { 181 Bindery bindery = context.getBindery(); 182 bindery.openStackFrame(params); 183 184 if (context.getController().isTracing()) { target.traceExpand(context); 186 } else { 187 target.expand(context); 188 } 189 190 bindery.closeStackFrame(); 191 } 192 193 } 194 195 } 196 197 | Popular Tags |