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 com.icl.saxon.pattern.Pattern; 8 import com.icl.saxon.trace.*; 10 import javax.xml.transform.*; 11 12 15 16 public class XSLTemplate extends StyleElement implements NodeHandler { 17 18 protected int modeNameCode = -1; 19 protected int templateFingerprint = -1; 20 protected Pattern match; 21 protected boolean prioritySpecified; 22 protected double priority; 23 protected Procedure procedure = new Procedure(); 24 protected boolean needsStackFrame; 25 26 30 31 public boolean mayContainTemplateBody() { 32 return true; 33 } 34 35 38 39 public int getTemplateFingerprint() { 40 41 43 try { 44 if (templateFingerprint==-1) { 45 StandardNames sn = getStandardNames(); 47 String nameAtt = getAttributeList().getValue(sn.NAME); 48 if (nameAtt!=null) { 49 templateFingerprint = 50 makeNameCode(nameAtt, false) & 0xfffff; 51 } 52 } 53 return templateFingerprint; 54 } catch (NamespaceException err) { 55 return -1; } 57 } 58 59 public int getMinImportPrecedence() { 60 return ((XSLStyleSheet)getDocumentElement()).getMinImportPrecedence(); 61 } 62 63 public boolean needsStackFrame() { 64 return this.needsStackFrame; 65 } 66 67 public void prepareAttributes() throws TransformerConfigurationException { 68 69 String modeAtt = null; 70 String nameAtt = null; 71 String priorityAtt = null; 72 String matchAtt = null; 73 74 StandardNames sn = getStandardNames(); 75 AttributeCollection atts = getAttributeList(); 76 77 for (int a=0; a<atts.getLength(); a++) { 78 int nc = atts.getNameCode(a); 79 int f = nc & 0xfffff; 80 if (f==sn.MODE) { 81 modeAtt = atts.getValue(a); 82 } else if (f==sn.NAME) { 83 nameAtt = atts.getValue(a); 84 } else if (f==sn.MATCH) { 85 matchAtt = atts.getValue(a); 86 } else if (f==sn.PRIORITY) { 87 priorityAtt = atts.getValue(a); 88 } else { 89 checkUnknownAttribute(nc); 90 } 91 } 92 try { 93 if (modeAtt!=null) { 94 if (!Name.isQName(modeAtt)) { 95 compileError("Mode name is not a valid QName"); 96 } 97 modeNameCode = makeNameCode(modeAtt, false); 98 } 99 100 if (nameAtt!=null) { 101 if (!Name.isQName(nameAtt)) { 102 compileError("Template name is not a valid QName"); 103 } 104 templateFingerprint = makeNameCode(nameAtt, false) & 0xfffff; 105 } 106 } catch (NamespaceException err) { 107 compileError(err.getMessage()); 108 } 109 110 prioritySpecified = (priorityAtt != null); 111 if (prioritySpecified) { 112 try { 113 priority = new Double (priorityAtt.trim()).doubleValue(); 114 } catch (NumberFormatException err) { 115 compileError("Invalid numeric value for priority (" + priority + ")"); 116 } 117 } 118 119 if (matchAtt != null) { 120 match = makePattern(matchAtt); 121 } 122 123 if (match==null && nameAtt==null) 124 compileError("xsl:template must have a a name or match attribute (or both)"); 125 126 } 127 128 129 public void validate() throws TransformerConfigurationException { 130 checkTopLevel(); 131 132 134 if (templateFingerprint!=-1) { 135 NodeImpl node = (NodeImpl)getPreviousSibling(); 137 while (node!=null) { 138 if (node instanceof XSLTemplate) { 139 XSLTemplate t = (XSLTemplate)node; 140 if (t.getTemplateFingerprint()==templateFingerprint && 141 t.getPrecedence()==this.getPrecedence()) { 142 compileError("There is another template with the same name and precedence"); 143 } 144 } 145 node = (NodeImpl)node.getPreviousSibling(); 146 } 147 } 148 149 } 150 151 155 156 public void preprocess() throws TransformerConfigurationException 157 { 158 RuleManager mgr = getPrincipalStyleSheet().getRuleManager(); 159 Mode mode = mgr.getMode(modeNameCode); 160 161 if (match!=null) { 162 NodeHandler handler = this; 163 if (getFirstChild()==null) { 164 handler = new NoOpHandler(); 166 } 167 if (prioritySpecified) { 168 mgr.setHandler(match, handler, mode, getPrecedence(), priority); 169 } else { 170 mgr.setHandler(match, handler, mode, getPrecedence()); 171 } 172 } 173 174 getPrincipalStyleSheet().allocateLocalSlots(procedure.getNumberOfVariables()); 175 needsStackFrame = (procedure.getNumberOfVariables() > 0); 176 177 } 178 179 183 184 public void process(Context context) throws TransformerException { 185 } 186 187 191 192 public void start( NodeInfo e, Context context ) throws TransformerException { 193 context.setCurrentTemplate(this); 194 195 if (context.getController().isTracing()) { traceExpand(context); 197 } else { 198 expand(context); 199 } 200 } 201 202 206 207 protected void traceExpand(Context context) throws TransformerException { 208 209 TraceListener listener = context.getController().getTraceListener(); 210 211 listener.enter(this, context); 212 expand(context); 213 listener.leave(this, context); 214 } 215 216 220 221 protected void expand(Context context) throws TransformerException { 222 ParameterSet p = null; 223 do { 224 context.setTailRecursion(null); 225 processChildren(context); 226 p = context.getTailRecursion(); 227 if (p!=null) { 228 context.getBindery().closeStackFrame(); 229 context.getBindery().openStackFrame(p); 230 } 231 } while (p!=null); 232 } 233 234 237 238 public Binding bindVariable(int fingerprint) throws XPathException { 239 throw new XPathException("The match pattern in xsl:template may not contain references to variables"); 240 } 241 242 245 246 public Procedure getProcedure() { 247 return procedure; 248 } 249 250 253 254 private final class NoOpHandler implements NodeHandler { 255 public void start( NodeInfo e, Context context ) {} 256 public boolean needsStackFrame() { 257 return false; 258 } 259 } 260 } 261 262 | Popular Tags |