📄 stylesheet.java
字号:
} // Compile in code to set the output configuration from <xsl:output> if (output != null) { // Set all the output settings files in the translet output.translate(classGen, constructor); } // Compile default decimal formatting symbols. // This is an implicit, nameless xsl:decimal-format top-level element. if (_numberFormattingUsed) DecimalFormatting.translateDefaultDFS(classGen, constructor); il.append(RETURN); constructor.stripAttributes(true); constructor.setMaxLocals(); constructor.setMaxStack(); classGen.addMethod(constructor.getMethod()); } /** * Compile a topLevel() method into the output class. This method is * called from transform() to handle all non-template top-level elements. * Returns the signature of the topLevel() method. * * Global variables/params and keys are first sorted to resolve * dependencies between them. The XSLT 1.0 spec does not allow a key * to depend on a variable. However, for compatibility with Xalan * interpretive, that type of dependency is allowed. Note also that * the buildKeys() method is still generated as it is used by the * LoadDocument class, but it no longer called from transform(). */ private String compileTopLevel(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = { Util.getJCRefType(DOM_INTF_SIG), Util.getJCRefType(NODE_ITERATOR_SIG), Util.getJCRefType(TRANSLET_OUTPUT_SIG) }; final String[] argNames = { DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME }; final InstructionList il = new InstructionList(); final MethodGenerator toplevel = new MethodGenerator(ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, argTypes, argNames, "topLevel", _className, il, classGen.getConstantPool()); toplevel.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); // Define and initialize 'current' variable with the root node final LocalVariableGen current = toplevel.addLocalVariable("current", com.sun.org.apache.bcel.internal.generic.Type.INT, il.getEnd(), null); final int setFilter = cpg.addInterfaceMethodref(DOM_INTF, "setFilter", "(Lcom/sun/org/apache/xalan/internal/xsltc/StripFilter;)V"); il.append(new PUSH(cpg, DTM.ROOT_NODE)); il.append(new ISTORE(current.getIndex())); // Create a new list containing variables/params + keys Vector varDepElements = new Vector(_globals); Enumeration elements = elements(); while (elements.hasMoreElements()) { final Object element = elements.nextElement(); if (element instanceof Key) { varDepElements.add(element); } } // Determine a partial order for the variables/params and keys varDepElements = resolveDependencies(varDepElements); // Translate vars/params and keys in the right order final int count = varDepElements.size(); for (int i = 0; i < count; i++) { final TopLevelElement tle = (TopLevelElement) varDepElements.elementAt(i); tle.translate(classGen, toplevel); if (tle instanceof Key) { final Key key = (Key) tle; _keys.put(key.getName(), key); } } // Compile code for other top-level elements Vector whitespaceRules = new Vector(); elements = elements(); while (elements.hasMoreElements()) { final Object element = elements.nextElement(); // xsl:decimal-format if (element instanceof DecimalFormatting) { ((DecimalFormatting)element).translate(classGen,toplevel); } // xsl:strip/preserve-space else if (element instanceof Whitespace) { whitespaceRules.addAll(((Whitespace)element).getRules()); } } // Translate all whitespace strip/preserve rules if (whitespaceRules.size() > 0) { Whitespace.translateRules(whitespaceRules,classGen); } if (classGen.containsMethod(STRIP_SPACE, STRIP_SPACE_PARAMS) != null) { il.append(toplevel.loadDOM()); il.append(classGen.loadTranslet()); il.append(new INVOKEINTERFACE(setFilter, 2)); } il.append(RETURN); // Compute max locals + stack and add method to class toplevel.stripAttributes(true); toplevel.setMaxLocals(); toplevel.setMaxStack(); toplevel.removeNOPs(); classGen.addMethod(toplevel.getMethod()); return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V"); } /** * This method returns a vector with variables/params and keys in the * order in which they are to be compiled for initialization. The order * is determined by analyzing the dependencies between them. The XSLT 1.0 * spec does not allow a key to depend on a variable. However, for * compatibility with Xalan interpretive, that type of dependency is * allowed and, therefore, consider to determine the partial order. */ private Vector resolveDependencies(Vector input) { /* DEBUG CODE - INGORE for (int i = 0; i < input.size(); i++) { final TopLevelElement e = (TopLevelElement) input.elementAt(i); System.out.println("e = " + e + " depends on:"); Vector dep = e.getDependencies(); for (int j = 0; j < (dep != null ? dep.size() : 0); j++) { System.out.println("\t" + dep.elementAt(j)); } } System.out.println("================================="); */ Vector result = new Vector(); while (input.size() > 0) { boolean changed = false; for (int i = 0; i < input.size(); ) { final TopLevelElement vde = (TopLevelElement) input.elementAt(i); final Vector dep = vde.getDependencies(); if (dep == null || result.containsAll(dep)) { result.addElement(vde); input.remove(i); changed = true; } else { i++; } } // If nothing was changed in this pass then we have a circular ref if (!changed) { ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR, input.toString(), this); getParser().reportError(Constants.ERROR, err); return(result); } } /* DEBUG CODE - INGORE System.out.println("================================="); for (int i = 0; i < result.size(); i++) { final TopLevelElement e = (TopLevelElement) result.elementAt(i); System.out.println("e = " + e); } */ return result; } /** * Compile a buildKeys() method into the output class. Note that keys * for the input document are created in topLevel(), not in this method. * However, we still need this method to create keys for documents loaded * via the XPath document() function. */ private String compileBuildKeys(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = { Util.getJCRefType(DOM_INTF_SIG), Util.getJCRefType(NODE_ITERATOR_SIG), Util.getJCRefType(TRANSLET_OUTPUT_SIG), com.sun.org.apache.bcel.internal.generic.Type.INT }; final String[] argNames = { DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME, "current" }; final InstructionList il = new InstructionList(); final MethodGenerator buildKeys = new MethodGenerator(ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, argTypes, argNames, "buildKeys", _className, il, classGen.getConstantPool()); buildKeys.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); final Enumeration elements = elements(); while (elements.hasMoreElements()) { // xsl:key final Object element = elements.nextElement(); if (element instanceof Key) { final Key key = (Key)element; key.translate(classGen, buildKeys); _keys.put(key.getName(),key); } } il.append(RETURN); // Compute max locals + stack and add method to class buildKeys.stripAttributes(true); buildKeys.setMaxLocals(); buildKeys.setMaxStack(); buildKeys.removeNOPs(); classGen.addMethod(buildKeys.getMethod()); return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+"I)V"); } /** * Compile transform() into the output class. This method is used to * initialize global variables and global parameters. The current node * is set to be the document's root node. */ private void compileTransform(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); /* * Define the the method transform with the following signature: * void transform(DOM, NodeIterator, HandlerBase) */ final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = new com.sun.org.apache.bcel.internal.generic.Type[3]; argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); final String[] argNames = new String[3]; argNames[0] = DOCUMENT_PNAME; argNames[1] = ITERATOR_PNAME; argNames[2] = TRANSLET_OUTPUT_PNAME; final InstructionList il = new InstructionList(); final MethodGenerator transf = new MethodGenerator(ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, argTypes, argNames, "transform", _className, il, classGen.getConstantPool()); transf.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); // Define and initialize current with the root node final LocalVariableGen current = transf.addLocalVariable("current", com.sun.org.apache.bcel.internal.generic.Type.INT, il.getEnd(), null); final String applyTemplatesSig = classGen.getApplyTemplatesSig(); final int applyTemplates = cpg.addMethodref(getClassName(), "applyTemplates", applyTemplatesSig); final int domField = cpg.addFieldref(getClassName(), DOM_FIELD, DOM_INTF_SIG); // push translet for PUTFIELD il.append(classGen.loadTranslet()); // prepare appropriate DOM implementation if (isMultiDocument()) { il.append(new NEW(cpg.addClass(MULTI_DOM_CLASS))); il.append(DUP); } il.append(classGen.loadTranslet()); il.append(transf.loadDOM()); il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS, "makeDOMAdapter", "("+DOM_INTF_SIG+")"+ DOM_ADAPTER_SIG))); // DOMAdapter is on the stack if (isMultiDocument()) { final int init = cpg.addMethodref(MULTI_DOM_CLASS, "<init>", "("+DOM_INTF_SIG+")V"); il.append(new INVOKESPECIAL(init)); // MultiDOM is on the stack } //store to _dom variable il.append(new PUTFIELD(domField)); // continue with globals initialization il.append(new PUSH(cpg, DTM.ROOT_NODE)); il.append(new ISTORE(current.getIndex())); // Transfer the output settings to the output post-processor il.append(classGen.loadTranslet()); il.append(transf.loadHandler()); final int index = cpg.addMethodref(TRANSLET_CLASS, "transferOutputSettings", "("+OUTPUT_HANDLER_SIG+")V"); il.append(new INVOKEVIRTUAL(index)); /* * Compile buildKeys() method. Note that this method is not * invoked here as keys for the input document are now created * in topLevel(). However, this method is still needed by the * LoadDocument class. */ final String keySig = compileBuildKeys(classGen); final int keyIdx = cpg.addMethodref(getClassName(), "buildKeys", keySig); // Look for top-level elements that need handling final Enumeration toplevel = elements(); if (_globals.size() > 0 || toplevel.hasMoreElements()) { // Compile method for handling top-level elements final String topLevelSig = compileTopLevel(classGen); // Get a reference to that method final int topLevelIdx = cpg.addMethodref(getClassName(), "topLevel", topLevelSig); // Push all parameters on the stack and call topLevel() il.append(classGen.loadTranslet()); // The 'this' pointer il.append(classGen.loadTranslet()); il.append(new GETFIELD(domField)); // The DOM reference il.append(transf.loadIterator()); il.append(transf.loadHandler()); // The output handler il.append(new INVOKEVIRTUAL(topLevelIdx)); } // start document il.append(transf.loadHandler()); il.append(transf.startDocument()); // push first arg for applyTemplates il.append(classGen.loadTranslet()); // push translet for GETFIELD to get DOM arg il.append(classGen.loadTranslet()); il.append(new GETFIELD(domField)); // push remaining 2 args il.append(transf.loadIterator()); il.append(transf.loadHandler()); il.append(new INVOKEVIRTUAL(applyTemplates)); // endDocument il.append(transf.loadHandler()); il.append(transf.endDocument()); il.append(RETURN); // Compute max locals + stack and add method to class transf.stripAttributes(true); transf.setMaxLocals(); transf.setMaxStack(); transf.removeNOPs(); classGen.addMethod(transf.getMethod()); } /** * Peephole optimization: Remove sequences of [ALOAD, POP]. */ private void peepHoleOptimization(MethodGenerator methodGen) { final String pattern = "`aload'`pop'`instruction'"; final InstructionList il = methodGen.getInstructionList(); final InstructionFinder find = new InstructionFinder(il); for(Iterator iter=find.search(pattern); iter.hasNext(); ) { InstructionHandle[] match = (InstructionHandle[])iter.next(); try { il.delete(match[0], match[1]); } catch (TargetLostException e) { // TODO: move target down into the list } } } public int addParam(Param param) { _globals.addElement(param); return _globals.size() - 1; } public int addVariable(Variable global) { _globals.addElement(global); return _globals.size() - 1; } public void display(int indent) { indent(indent); Util.println("Stylesheet"); displayContents(indent + IndentIncrement); } // do we need this wrapper ????? public String getNamespace(String prefix) { return lookupNamespace(prefix); } public String getClassName() { return _className; } public Vector getTemplates() { return _templates; } public Vector getAllValidTemplates() { // Return templates if no imported/included stylesheets if (_includedStylesheets == null) { return _templates; } // Is returned value cached? if (_allValidTemplates == null) { Vector templates = new Vector(); templates.addAll(_templates); int size = _includedStylesheets.size(); for (int i = 0; i < size; i++) { Stylesheet included =(Stylesheet)_includedStylesheets.elementAt(i); templates.addAll(included.getAllValidTemplates()); } //templates.addAll(_templates); // Cache results in top-level stylesheet only if (_parentStylesheet != null) { return templates; } _allValidTemplates = templates; } return _allValidTemplates; } protected void addTemplate(Template template) { _templates.addElement(template); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -