📄 stylesheet.java
字号:
return false; } else { return _hasLocalParams.booleanValue(); } } /** * Adds a single prefix mapping to this syntax tree node. * @param prefix Namespace prefix. * @param uri Namespace URI. */ protected void addPrefixMapping(String prefix, String uri) { if (prefix.equals(EMPTYSTRING) && uri.equals(XHTML_URI)) return; super.addPrefixMapping(prefix, uri); } /** * Store extension URIs */ private void extensionURI(String prefixes, SymbolTable stable) { if (prefixes != null) { StringTokenizer tokens = new StringTokenizer(prefixes); while (tokens.hasMoreTokens()) { final String prefix = tokens.nextToken(); final String uri = lookupNamespace(prefix); if (uri != null) { _extensions.put(uri, prefix); } } } } public boolean isExtension(String uri) { return (_extensions.get(uri) != null); } public void excludeExtensionPrefixes(Parser parser) { final SymbolTable stable = parser.getSymbolTable(); final String excludePrefixes = getAttribute("exclude-result-prefixes"); final String extensionPrefixes = getAttribute("extension-element-prefixes"); // Exclude XSLT uri stable.excludeURI(Constants.XSLT_URI); stable.excludeNamespaces(excludePrefixes); stable.excludeNamespaces(extensionPrefixes); extensionURI(extensionPrefixes, stable); } /** * Parse the version and uri fields of the stylesheet and add an * entry to the symbol table mapping the name <tt>__stylesheet_</tt> * to an instance of this class. */ public void parseContents(Parser parser) { final SymbolTable stable = parser.getSymbolTable(); /* // Make sure the XSL version set in this stylesheet if ((_version == null) || (_version.equals(EMPTYSTRING))) { reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR,"version"); } // Verify that the version is 1.0 and nothing else else if (!_version.equals("1.0")) { reportError(this, parser, ErrorMsg.XSL_VERSION_ERR, _version); } */ // Add the implicit mapping of 'xml' to the XML namespace URI addPrefixMapping("xml", "http://www.w3.org/XML/1998/namespace"); // Report and error if more than one stylesheet defined final Stylesheet sheet = stable.addStylesheet(_name, this); if (sheet != null) { // Error: more that one stylesheet defined ErrorMsg err = new ErrorMsg(ErrorMsg.MULTIPLE_STYLESHEET_ERR,this); parser.reportError(Constants.ERROR, err); } // If this is a simplified stylesheet we must create a template that // grabs the root node of the input doc ( <xsl:template match="/"/> ). // This template needs the current element (the one passed to this // method) as its only child, so the Template class has a special // method that handles this (parseSimplified()). if (_simplified) { stable.excludeURI(XSLT_URI); Template template = new Template(); template.parseSimplified(this, parser); } // Parse the children of this node else { parseOwnChildren(parser); } } /** * Parse all direct children of the <xsl:stylesheet/> element. */ public final void parseOwnChildren(Parser parser) { final Vector contents = getContents(); final int count = contents.size(); // We have to scan the stylesheet element's top-level elements for // variables and/or parameters before we parse the other elements for (int i = 0; i < count; i++) { SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i); if ((child instanceof VariableBase) || (child instanceof NamespaceAlias)) { parser.getSymbolTable().setCurrentNode(child); child.parseContents(parser); } } // Now go through all the other top-level elements... for (int i = 0; i < count; i++) { SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i); if (!(child instanceof VariableBase) && !(child instanceof NamespaceAlias)) { parser.getSymbolTable().setCurrentNode(child); child.parseContents(parser); } // All template code should be compiled as methods if the // <xsl:apply-imports/> element was ever used in this stylesheet if (!_templateInlining && (child instanceof Template)) { Template template = (Template)child; String name = "template$dot$" + template.getPosition(); template.setName(parser.getQName(name)); } } } public void processModes() { if (_defaultMode == null) _defaultMode = new Mode(null, this, Constants.EMPTYSTRING); _defaultMode.processPatterns(_keys); final Enumeration modes = _modes.elements(); while (modes.hasMoreElements()) { final Mode mode = (Mode)modes.nextElement(); mode.processPatterns(_keys); } } private void compileModes(ClassGenerator classGen) { _defaultMode.compileApplyTemplates(classGen); final Enumeration modes = _modes.elements(); while (modes.hasMoreElements()) { final Mode mode = (Mode)modes.nextElement(); mode.compileApplyTemplates(classGen); } } public Mode getMode(QName modeName) { if (modeName == null) { if (_defaultMode == null) { _defaultMode = new Mode(null, this, Constants.EMPTYSTRING); } return _defaultMode; } else { Mode mode = (Mode)_modes.get(modeName); if (mode == null) { final String suffix = Integer.toString(_nextModeSerial++); _modes.put(modeName, mode = new Mode(modeName, this, suffix)); } return mode; } } /** * Type check all the children of this node. */ public Type typeCheck(SymbolTable stable) throws TypeCheckError { final int count = _globals.size(); for (int i = 0; i < count; i++) { final VariableBase var = (VariableBase)_globals.elementAt(i); var.typeCheck(stable); } return typeCheckContents(stable); } /** * Translate the stylesheet into JVM bytecodes. */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { translate(); } private void addDOMField(ClassGenerator classGen) { final FieldGen fgen = new FieldGen(ACC_PUBLIC, Util.getJCRefType(DOM_INTF_SIG), DOM_FIELD, classGen.getConstantPool()); classGen.addField(fgen.getField()); } /** * Add a static field */ private void addStaticField(ClassGenerator classGen, String type, String name) { final FieldGen fgen = new FieldGen(ACC_PROTECTED|ACC_STATIC, Util.getJCRefType(type), name, classGen.getConstantPool()); classGen.addField(fgen.getField()); } /** * Translate the stylesheet into JVM bytecodes. */ public void translate() { _className = getXSLTC().getClassName(); // Define a new class by extending TRANSLET_CLASS final ClassGenerator classGen = new ClassGenerator(_className, TRANSLET_CLASS, Constants.EMPTYSTRING, ACC_PUBLIC | ACC_SUPER, null, this); addDOMField(classGen); // Compile transform() to initialize parameters, globals & output // and run the transformation compileTransform(classGen); // Translate all non-template elements and filter out all templates final Enumeration elements = elements(); while (elements.hasMoreElements()) { Object element = elements.nextElement(); // xsl:template if (element instanceof Template) { // Separate templates by modes final Template template = (Template)element; //_templates.addElement(template); getMode(template.getModeName()).addTemplate(template); } // xsl:attribute-set else if (element instanceof AttributeSet) { ((AttributeSet)element).translate(classGen, null); } else if (element instanceof Output) { // save the element for later to pass to compileConstructor Output output = (Output)element; if (output.enabled()) _lastOutputElement = output; } else { // Global variables and parameters are handled elsewhere. // Other top-level non-template elements are ignored. Literal // elements outside of templates will never be output. } } checkOutputMethod(); processModes(); compileModes(classGen); compileStaticInitializer(classGen); compileConstructor(classGen, _lastOutputElement); if (!getParser().errorsFound()) { getXSLTC().dumpClass(classGen.getJavaClass()); } } /** * Compile the namesArray, urisArray and typesArray into * the static initializer. They are read-only from the * translet. All translet instances can share a single * copy of this informtion. */ private void compileStaticInitializer(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = new InstructionList(); final MethodGenerator staticConst = new MethodGenerator(ACC_PUBLIC|ACC_STATIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, null, null, "<clinit>", _className, il, cpg); addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMES_ARRAY_FIELD); addStaticField(classGen, "[" + STRING_SIG, STATIC_URIS_ARRAY_FIELD); addStaticField(classGen, "[I", STATIC_TYPES_ARRAY_FIELD); addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMESPACE_ARRAY_FIELD); // Create fields of type char[] that will contain literal text from // the stylesheet. final int charDataFieldCount = getXSLTC().getCharacterDataCount(); for (int i = 0; i < charDataFieldCount; i++) { addStaticField(classGen, STATIC_CHAR_DATA_FIELD_SIG, STATIC_CHAR_DATA_FIELD+i); } // Put the names array into the translet - used for dom/translet mapping final Vector namesIndex = getXSLTC().getNamesIndex(); int size = namesIndex.size(); String[] namesArray = new String[size]; String[] urisArray = new String[size]; int[] typesArray = new int[size]; int index; for (int i = 0; i < size; i++) { String encodedName = (String)namesIndex.elementAt(i); if ((index = encodedName.lastIndexOf(':')) > -1) { urisArray[i] = encodedName.substring(0, index); } index = index + 1; if (encodedName.charAt(index) == '@') { typesArray[i] = DTM.ATTRIBUTE_NODE; index++; } else if (encodedName.charAt(index) == '?') { typesArray[i] = DTM.NAMESPACE_NODE; index++; } else { typesArray[i] = DTM.ELEMENT_NODE; } if (index == 0) { namesArray[i] = encodedName; } else { namesArray[i] = encodedName.substring(index); } } il.append(new PUSH(cpg, size)); il.append(new ANEWARRAY(cpg.addClass(STRING))); for (int i = 0; i < size; i++) { final String name = namesArray[i]; il.append(DUP); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, name)); il.append(AASTORE); } il.append(new PUTSTATIC(cpg.addFieldref(_className, STATIC_NAMES_ARRAY_FIELD, NAMES_INDEX_SIG))); il.append(new PUSH(cpg, size)); il.append(new ANEWARRAY(cpg.addClass(STRING))); for (int i = 0; i < size; i++) { final String uri = urisArray[i]; il.append(DUP); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, uri)); il.append(AASTORE); } il.append(new PUTSTATIC(cpg.addFieldref(_className, STATIC_URIS_ARRAY_FIELD, URIS_INDEX_SIG))); il.append(new PUSH(cpg, size)); il.append(new NEWARRAY(BasicType.INT)); for (int i = 0; i < size; i++) { final int nodeType = typesArray[i]; il.append(DUP); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, nodeType)); il.append(IASTORE); } il.append(new PUTSTATIC(cpg.addFieldref(_className, STATIC_TYPES_ARRAY_FIELD, TYPES_INDEX_SIG))); // Put the namespace names array into the translet final Vector namespaces = getXSLTC().getNamespaceIndex(); il.append(new PUSH(cpg, namespaces.size())); il.append(new ANEWARRAY(cpg.addClass(STRING))); for (int i = 0; i < namespaces.size(); i++) { final String ns = (String)namespaces.elementAt(i); il.append(DUP); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, ns)); il.append(AASTORE); } il.append(new PUTSTATIC(cpg.addFieldref(_className, STATIC_NAMESPACE_ARRAY_FIELD, NAMESPACE_INDEX_SIG))); // Grab all the literal text in the stylesheet and put it in a char[] final int charDataCount = getXSLTC().getCharacterDataCount(); final int toCharArray = cpg.addMethodref(STRING, "toCharArray", "()[C"); for (int i = 0; i < charDataCount; i++) { il.append(new PUSH(cpg, getXSLTC().getCharacterData(i))); il.append(new INVOKEVIRTUAL(toCharArray)); il.append(new PUTSTATIC(cpg.addFieldref(_className, STATIC_CHAR_DATA_FIELD+i, STATIC_CHAR_DATA_FIELD_SIG))); } il.append(RETURN); staticConst.stripAttributes(true); staticConst.setMaxLocals(); staticConst.setMaxStack(); classGen.addMethod(staticConst.getMethod()); } /** * Compile the translet's constructor */ private void compileConstructor(ClassGenerator classGen, Output output) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = new InstructionList(); final MethodGenerator constructor = new MethodGenerator(ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, null, null, "<init>", _className, il, cpg); // Call the constructor in the AbstractTranslet superclass il.append(classGen.loadTranslet()); il.append(new INVOKESPECIAL(cpg.addMethodref(TRANSLET_CLASS, "<init>", "()V"))); il.append(classGen.loadTranslet()); il.append(new GETSTATIC(cpg.addFieldref(_className, STATIC_NAMES_ARRAY_FIELD, NAMES_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, NAMES_INDEX, NAMES_INDEX_SIG))); il.append(classGen.loadTranslet()); il.append(new GETSTATIC(cpg.addFieldref(_className, STATIC_URIS_ARRAY_FIELD, URIS_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, URIS_INDEX, URIS_INDEX_SIG))); il.append(classGen.loadTranslet()); il.append(new GETSTATIC(cpg.addFieldref(_className, STATIC_TYPES_ARRAY_FIELD, TYPES_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, TYPES_INDEX, TYPES_INDEX_SIG))); il.append(classGen.loadTranslet()); il.append(new GETSTATIC(cpg.addFieldref(_className, STATIC_NAMESPACE_ARRAY_FIELD, NAMESPACE_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, NAMESPACE_INDEX, NAMESPACE_INDEX_SIG))); il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, AbstractTranslet.CURRENT_TRANSLET_VERSION)); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, TRANSLET_VERSION_INDEX, TRANSLET_VERSION_INDEX_SIG))); if (_hasIdCall) { il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, Boolean.TRUE)); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, HASIDCALL_INDEX, HASIDCALL_INDEX_SIG)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -