在我们的项目中,我们目前转向Java 8,并希望现在使用内部XML库而不是其他库。 为此,我们删除了我们的类路径中的xalan.jar。
这在尝试呈现XML文件时会导致ClassNotFoundExceptions。 在我们用于转换XML文件的XSL样式表中,我们还调用外部Java方法,如以下示例所示:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:java="http://xml.apache.org/xalan/java">
...
<xsl:template name="example">
<fo:block>
<xsl:value-of select="java:my.package.name.JavaClass.testMethod('test')"/>
</fo:block>
</xsl:template>
...
但是,始终应该调用外部方法testMethod()
时,进程会因ClassNotFoundException而停止。
我调试了com.sun.org.apache.xalan.internal.xsltc.compiler.FunctionCall
类中的代码,发现XSLTC尝试实例化my.package.name.JavaClass
以调用testMethod()
。哪个没关系。但...
尝试在com.sun.org.apache.xalan.internal.utils.ObjectFactory
的以下代码中实例化/加载该类:
/**
* Find a Class using the same class loader for the ObjectFactory by default
* or boot class loader when Security Manager is in place
*/
public static Class<?> findProviderClass(String className, boolean doFallback)
throws ClassNotFoundException, ConfigurationError
{
return findProviderClass (className,
findClassLoader (), doFallback);
}
进一步调用findClassLoader()
以获取正确的类加载器来加载我的JavaClass
:
/**
* Figure out which ClassLoader to use. For JDK 1.2 and later use
* the context ClassLoader.
*/
public static ClassLoader findClassLoader()
{
if (System.getSecurityManager()!=null) {
//this will ensure bootclassloader is used
return null;
}
// Figure out which ClassLoader to use for loading the provider
// class. If there is a Context ClassLoader then use it.
ClassLoader context = SecuritySupport.getContextClassLoader();
ClassLoader system = SecuritySupport.getSystemClassLoader();
ClassLoader chain = system;
while (true) {
if (context == chain) {
...loop to get correct class loader
}
现在在我们的项目中,我们遇到了'问题',我们有一个SecurityManager实现,这意味着上面的实现只返回null
而不是上下文类加载器。
这再次意味着我的类被尝试加载了启动类加载器,它不知道我的类,因此抛出异常。删除SecurityManager将返回能够加载我的类的上下文类加载器,并且可以成功转换XML。
所以 - 如果你还在这里并且睡着了 - 有没有办法在XSL样式表中仍然使用我的外部Java方法?在这种情况下有没有办法加载我的课程? 我想到了以下可能的解决方案,但它们都不能让我满意:
使用反射以如下方式在XSL中创建我的JavaClass实例:
但是,最后一种方法也不起作用,因为该类也加载了AppClassLoader,并且在解析过程中可能也不可用。但也许有类似的解决方案?
提前致谢。
最诚挚的问候, 延
答案 0 :(得分:0)
这样的事情是否有效:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:myHelper="http://xml.apache.org/xalan/java/my.package.name.JavaClass">
...
<xsl:template name="example">
<fo:block>
<xsl:value-of select="myHelper:testMethod('test')"/>
</fo:block>
</xsl:template>
如何在样式表声明中指定命名空间(在本例中为 myHelper )取决于您用于处理XSL的内容,上面的示例适用于Xalan。