曾经有两篇介绍了在 XSLT 里如何调用 C# 或 Js 写的函数,其中用到了与微软相关的,像:xmlns:msxsl="urn:schemas-microsoft-com:xslt", <msxsl:script implements-prefix="unmifn" language="C#">。回到了 Java 环境同样得考虑在 XSLT 中如何调用 Java 的方法,毕竟在 XSLT 外处理内容要方便许多。
参考了一些网上的文章,大多讲的不怎么好理解与应用,未尝试之前不免让人想缩手。其实做起来可以更简单些,两步而已:
1) 声明时指定包名和函数前缀
2) 调用时加上前缀和类名及静态方法,传入参数
要想再深入些,可注意有时候 Java 函数应该传入的参数类型是什么?是否能调用非静态方法,public 是最基本的要求,以及通过什么组件来调用的等等。
下面来看例子,在 xslt 里这样写(如 example.xslt):
1 2 3 4 5 6 7 8 9 10 |
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="cc.unmi.commons" exclude-result-prefixes="java"> <xsl:output method="xml"/> <xsl:template match="user/name"> <li><xsl:value-of select='java:XsltFunctions.replace(.)'/></li> </xsl:template> </xsl:stylesheet> |
说明:我们把要调用的方法所在类放在 cc.unmi.commons 包中,别名为 java,用 exclude-result-prefixes="java" 使用 java 不被包含在声明中。使用代码 java:XsltFunctions.replace(.) 来 cc.unmi.commons.XsltFunctions.replace(String str) 方法,传入的参数是点表示当前节点。
再看 Java 类及其中方法 replace 的定义:
1 2 3 4 5 6 7 |
package cc.unmi.commons; public class XsltFunctions { public static String replace(String src){ return dest.replace("unmi", "unmi.cc"); } } |
这个方法它应该是个 public static 的,这里只是作了简单的替换操作,要知道从 XSLT 来到了 Java 的世界里,可以在这里做非常灵活、复杂的事情。
假设是这样一个 xml 文件(如 example.xml):
1 2 3 4 5 |
<user> <name>unmi</name> <blog>http://unmi.cc</blog> <email>fantasia@sina.com</email> </user> |
完成转换的 Java 代表如下,只需用到 JDK 自带的 javax.xml.transform 下的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public static void transfer() throws Exception{ Source xmlSource = new StreamSource("example.xml"); Source xsltSource = new StreamSource("example.xslt"); TransformerFactory transfact = TransformerFactory.newInstance(); StringWriter sw = new StringWriter(); Result result = new StreamResult(sw); Transformer trans = transfact.newTransformer(xsltSource); trans.transform(xmlSource, result); System.out.println(sw.toString()); } |
上面的代码在 Eclipse 或命令行下运行时 javax.xml.transform.TransformerFactory 的实现是 org.apache.xalan.processor.TransformerFactoryImpl
在 Tomcat 下的实现默认是 net.sf.saxon.TransformerFactoryImpl。你可以用下面两种方式来指定 XSLT 转换时的实现类
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl"); //全局方式
TransformerFactory transfact = TransformerFactory.newInstance("org.apache.xalan.processor.TransformerFactoryImpl", YourClass.class.getClassLoader());
xalan 的兼容性要强,但是使用 saxon 的实现时,xstl 中的写法又不一样了,参考:XSLT 调用 Java 的类方法 -- Tomcat 环境
看看 sw.toString() 的内容吧。
中间的实现好像也是通过 Xalan 组件的。另外,除了可用 xmlns:java="cc.unmi.commons" 直接指定包名的方法,还可多了解下它还能不能使用别的方式,比如加载网络包等等。
参考:1. 通过XSLT访问Java代码
2. 简单的 Xalan 扩展函数
3. Call Java methods from within the XSLT
4. Extending XSLT with Java
本文链接 https://yanbin.blog/xslt-call-java-method/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。