XSLTC使用非法方法名创建类

时间:2016-11-30 11:26:01

标签: java xsltc

我尝试使用XSLTC编译XSLT转换,但结果类不可用,因为它包含非法名称的方法。

为了便于说明,这里是我使用的样式表的(简化)版本:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns1="http://some.weird/Namespace#/Definition"
    xmlns="http://another.strange/Namespace#/Definition">

    <xsl:template match="ns1:*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="text()">
        <xsl:value-of select="." />
    </xsl:template>
</xsl:stylesheet>

这要做的是将XML文件的所有元素的命名空间更改为另一个元素,因此我基本上使用修改后的身份转换。但是,XSLTC似乎遇到了#&#39;#&#39;名称空间URI中的字符(尽管据我所知,它们应该是合法的)。因为XSLTC在编译上面时创建的类文件看起来像这样(当然是反编译的):

import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.TransletException;
import org.apache.xalan.xsltc.dom.UnionIterator;
import org.apache.xalan.xsltc.runtime.AbstractTranslet;
import org.apache.xalan.xsltc.runtime.BasisLibrary;
import org.apache.xml.dtm.DTMAxisIterator;
import org.apache.xml.serializer.SerializationHandler;

public class ChangeNamespace extends AbstractTranslet {
    public DOM _dom;
    protected static String[] _sNamesArray = new String[0];
    protected static String[] _sUrisArray = new String[0];
    protected static int[] _sTypesArray = new int[0];
    protected static String[] _sNamespaceArray = new String[0];

    public void buildKeys(DOM var1, DTMAxisIterator var2, SerializationHandler var3, int var4) throws TransletException {
    }

    public void topLevel(DOM var1, DTMAxisIterator var2, SerializationHandler var3) throws TransletException {
        boolean var4 = false;
    }

    public void transform(DOM var1, DTMAxisIterator var2, SerializationHandler var3) throws TransletException {
        this._dom = this.makeDOMAdapter(var1);
        boolean var4 = false;
        this.transferOutputSettings(var3);
        this.buildKeys(this._dom, var2, var3, 0);
        this.topLevel(this._dom, var2, var3);
        var3.startDocument();
        this.applyTemplates(this._dom, var2, var3);
        var3.endDocument();
    }

    public void http$colon$$slash$$slash$another$dot$strange$slash$Namespace#$slash$Definition$colon$template$dot$0(DOM var1, DTMAxisIterator var2, SerializationHandler var3, int var4) {
        String var5 = BasisLibrary.getLocalName(var1.getNodeName(var4));
        BasisLibrary.checkQName(var5);
        String var10001 = BasisLibrary.startXslElement(var5, (String)null, var3, var1, var4);
        this.applyTemplates(var1, var1.getChildren(var4), var3);
        var3.endElement(var10001);
    }

    public void http$colon$$slash$$slash$another$dot$strange$slash$Namespace#$slash$Definition$colon$template$dot$1(DOM var1, DTMAxisIterator var2, SerializationHandler var3, int var4) {
        String var5;
        if((var5 = var1.shallowCopy(var4, var3)) != null) {
            int var6 = var5.length();
            this.applyTemplates(var1, (new UnionIterator(var1)).addIterator(var1.getAxisIterator(2)).addIterator(var1.getAxisIterator(3)).setStartNode(var4), var3);
            if(var6 != 0) {
                var3.endElement(var5);
            }
        }

    }

    public void http$colon$$slash$$slash$another$dot$strange$slash$Namespace#$slash$Definition$colon$template$dot$2(DOM var1, DTMAxisIterator var2, SerializationHandler var3, int var4) {
        var1.characters(var4, var3);
    }

    public final void applyTemplates(DOM var1, DTMAxisIterator var2, SerializationHandler var3) throws TransletException {
        int var4;
        while((var4 = var2.next()) >= 0) {
            switch(var1.getExpandedTypeID(var4)) {
            case 0:
            case 9:
                this.applyTemplates(var1, var1.getChildren(var4), var3);
                break;
            case 1:
                if(var1.getNamespaceName(var4).equals("http://some.weird/Namespace#/Definition")) {
                    this.http$colon$$slash$$slash$another$dot$strange$slash$Namespace#$slash$Definition$colon$template$dot$0(var1, var2, var3, var4);
                    break;
                } else {
                    var4 = var4;
                }
            case 2:
            case 7:
            case 8:
                this.http$colon$$slash$$slash$another$dot$strange$slash$Namespace#$slash$Definition$colon$template$dot$1(var1, var2, var3, var4);
                break;
            case 3:
                this.http$colon$$slash$$slash$another$dot$strange$slash$Namespace#$slash$Definition$colon$template$dot$2(var1, var2, var3, var4);
            case 4:
            case 5:
            case 6:
            case 10:
            case 11:
            case 12:
            case 13:
            }
        }

    }

    public ChangeNamespace() {
        super.namesArray = _sNamesArray;
        super.urisArray = _sUrisArray;
        super.typesArray = _sTypesArray;
        super.namespaceArray = _sNamespaceArray;
        super.transletVersion = 101;
    }
}

注意&#39;#&#39;在一些生成的方法名称中,根据Java规范是非法的,毫不奇怪,当我实际尝试使用该类时,它会导致类加载器的类型加载。

任何想法,如果我能以某种方式让XSLTC将XSL编译成有效的东西?我是否可以某种方式修改我的样式表以完成同样不会导致此问题的事情?

不,我不能自己更改命名空间,它们已经修复,因为它们属于我必须处理但不影响的外部系统。

1 个答案:

答案 0 :(得分:0)

通过调试XSLTC代码进一步调查问题,我设法将原因缩小到调用类escape中名为org.apache.xalan.xsltc.compiler.util.Util的方法。

这就是实际源代码(Xalan 2.7.2)中的样子:

public static String escape(String input) {
    return replace(input, ".-/:", new String[]{"$dot$", "$dash$", "$slash$", "$colon$"});
}

当尝试从字符串创建方法名称时(例如,在我的情况下,名称空间),从几个地方调用它,虽然这种天真的实现对于该目的而言是令人震惊的,如我的情况所示。返回的字符串无需任何进一步修改或检查即可使用,以确保生成的名称在Java中实际有效。

我的解决方案(我将详细介绍此处,因为它不是一个良好解决方案 - 它不适合胆小的人和任何想要的人做同样的事情应该有足够的专业知识来复制它而无需额外的指令,或远离这种诡计),实际上是使用字节码操作来代替上述方法的主体,也可以处理&#39;#& #39;字符。这是一个绝望的举动,但至少对我来说是有用的。