寻求saxon.evaluate()替代方案:Saxon-HE最新版不支持,使用XSLT 2.0
Saxon-HE中
saxon:evaluate()的替代方案&自定义实现 哈喽,针对你在XSLT 2.0环境下,遇到Saxon-HE最新版本移除了saxon:evaluate()方法的问题,我给你整理了几个可行的替代方案,还有如果必须要动态表达式解析功能的话,自定义Java扩展函数的实现思路:
一、优先用标准XSLT特性替代
saxon:evaluate()本来是Saxon的专有扩展,新版移除它主要是因为安全风险,所以优先考虑标准特性会更稳妥:
1. 升级到XSLT 3.0使用标准xsl:evaluate
如果你的项目可以升级到XSLT 3.0,那W3C标准的xsl:evaluate函数是最优解——Saxon-HE完全支持这个标准函数,用法和旧的saxon:evaluate几乎一致,还更安全可控。示例代码:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <!-- 动态表达式字符串 --> <xsl:variable name="expr" select="'//book[price > 10]'" /> <!-- 执行表达式并输出结果 --> <xsl:copy-of select="xsl:evaluate($expr)" /> </xsl:template> </xsl:stylesheet>
只要在样式声明里把version设为3.0,就能直接用这个函数。
2. 坚守XSLT 2.0的静态分支方案
如果必须留在XSLT 2.0环境,那可以把动态逻辑拆解成预定义的分支逻辑,通过参数来控制执行,避免动态解析字符串。比如:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <!-- 用参数指定要执行的逻辑类型 --> <xsl:call-template name="dynamic-filter"> <xsl:with-param name="filter-type" select="'expensive'" /> </xsl:call-template> </xsl:template> <xsl:template name="dynamic-filter"> <xsl:param name="filter-type" /> <xsl:choose> <xsl:when test="$filter-type = 'expensive'"> <xsl:copy-of select="//book[price > 10]" /> </xsl:when> <xsl:when test="$filter-type = 'cheap'"> <xsl:copy-of select="//book[price < 5]" /> </xsl:when> </xsl:choose> </xsl:template> </xsl:stylesheet>
这种方式虽然灵活性不如动态解析,但完全符合XSLT 2.0标准,没有安全隐患。
二、自定义Java扩展函数实现类似saxon:evaluate的功能
如果你的业务场景必须动态解析字符串表达式,且无法升级到XSLT 3.0,那可以自己写一个Java扩展函数集成到Saxon-HE中。下面是一个基础的实现:
1. 编写Java扩展函数类
import net.sf.saxon.expr.XPathContext; import net.sf.saxon.lib.ExtensionFunctionCall; import net.sf.saxon.lib.ExtensionFunctionDefinition; import net.sf.saxon.om.Sequence; import net.sf.saxon.om.StructuredQName; import net.sf.saxon.trans.XPathException; import net.sf.saxon.value.SequenceType; import net.sf.saxon.value.StringValue; public class CustomEvaluate extends ExtensionFunctionDefinition { // 定义函数的命名空间和名称 @Override public StructuredQName getFunctionQName() { return new StructuredQName("custom", "http://your-domain.com/xsl-extensions", "evaluate"); } // 定义参数类型:单个字符串(表达式) @Override public SequenceType[] getArgumentTypes() { return new SequenceType[]{SequenceType.SINGLE_STRING}; } // 定义返回值类型:任意序列 @Override public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { return SequenceType.ANY_SEQUENCE; } // 实现函数调用逻辑 @Override public ExtensionFunctionCall makeCallExpression() { return new ExtensionFunctionCall() { @Override public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { // 获取传入的表达式字符串 String exprStr = ((StringValue) arguments[0].head()).getStringValue(); // 编译并执行XPath表达式 return context.getConfiguration().compileQuery(exprStr).evaluate(context.getContextItem(), context); } }; } }
2. 在XSLT中注册并使用
首先在XSLT样式中引入自定义命名空间:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:custom="http://your-domain.com/xsl-extensions" extension-element-prefixes="custom">
然后在Java代码中把这个函数注册到Saxon的配置里:
import net.sf.saxon.Configuration; import net.sf.saxon.TransformerFactoryImpl; import javax.xml.transform.TransformerFactory; // 获取Saxon的配置实例 TransformerFactory factory = TransformerFactory.newInstance(); Configuration config = ((TransformerFactoryImpl) factory).getConfiguration(); // 注册自定义扩展函数 config.registerExtensionFunction(new CustomEvaluate());
最后就可以在XSLT中调用这个自定义函数了:
<xsl:variable name="expr" select="'//book[price > 10]'" /> <xsl:copy-of select="custom:evaluate($expr)" />
重要注意事项
- 安全风险:这个自定义函数和原
saxon:evaluate一样,如果表达式字符串来自不可信来源,可能会导致XPath注入攻击,一定要确保表达式的安全性。 - 依赖版本:确保你的项目引入了对应版本的Saxon-HE依赖(比如Maven中
net.sf.saxon:Saxon-HE:12.x及以上)。 - 功能扩展:上面的实现只支持简单的XPath表达式,如果需要传递参数或者支持更复杂的场景,可以修改代码添加参数处理逻辑。
内容的提问来源于stack exchange,提问作者Santosh Kumar
相关产品推荐
相关产品推荐

