如何让Saxon 9编译存在类型不兼容的XPath表达式?
解决Saxon 9编译XPath 1.0风格类型不兼容表达式的问题
编译阶段绕过类型检查
Saxon默认以XPath 2.0+模式运行,编译时会严格校验类型兼容性,因此position() = '1'这类依赖隐式类型转换的XPath 1.0表达式会直接报错。要实现编译,只需将Saxon配置为XPath 1.0兼容模式:
import net.sf.saxon.Configuration; import net.sf.saxon.xpath.XPathEvaluator; import net.sf.saxon.expr.Expression; // 初始化XPath 1.0兼容的配置 Configuration config = new Configuration(); config.setXPathLanguageVersion("1.0"); // 基于该配置创建XPathEvaluator XPathEvaluator evaluator = new XPathEvaluator(config); // 编译目标表达式不再报错 Expression compiledExpr = evaluator.compile("position() = '1'");
遍历编译后的Expression树修复类型问题
编译完成后,你可以通过Saxon的表达式遍历API,递归检查并修改类型不兼容的节点。例如针对position() = '1'的场景,可将字符串字面量'1'转换为数值字面量,或为比较操作添加显式类型转换:
自定义表达式访问器实现修复逻辑
import net.sf.saxon.expr.EqualityComparison; import net.sf.saxon.expr.Literal; import net.sf.saxon.expr.StringLiteral; import net.sf.saxon.expr.NumericLiteral; import net.sf.saxon.expr.ExpressionVisitor; import net.sf.saxon.expr.PositionCall; import net.sf.saxon.trans.XPathException; public class TypeFixVisitor extends ExpressionVisitor { @Override public Expression visitExpression(Expression expr) throws XPathException { // 处理相等比较节点 if (expr instanceof EqualityComparison) { EqualityComparison eq = (EqualityComparison) expr; Expression lhs = eq.getLhsExpression(); Expression rhs = eq.getRhsExpression(); // 检测左侧是position()调用、右侧是字符串字面量的场景 if (lhs instanceof PositionCall && rhs instanceof StringLiteral) { StringLiteral strLit = (StringLiteral) rhs; try { // 将字符串转换为数值字面量 double numValue = Double.parseDouble(strLit.getStringValue()); NumericLiteral numLit = new NumericLiteral(numValue); // 替换原右侧表达式 eq.setRhsExpression(numLit); } catch (NumberFormatException e) { // 处理无法转换的字符串,可根据业务需求自定义降级逻辑 } } } // 递归处理子表达式,确保嵌套节点被覆盖 expr = super.visitExpression(expr); return expr; } } // 使用示例 TypeFixVisitor visitor = new TypeFixVisitor(); visitor.setConfiguration(config); Expression fixedExpr = visitor.visitExpression(compiledExpr);
注意事项
- Saxon 9.x的内部表达式API与后续版本存在差异,使用时需对应版本的官方文档;
- 遍历修改表达式树时,需确保所有子节点都被递归处理,避免遗漏嵌套的类型不兼容场景;
- 若需支持更复杂的隐式类型转换场景,可扩展访问器的处理逻辑,覆盖更多表达式节点类型。
内容的提问来源于stack exchange,提问作者martin
相关产品推荐
相关产品推荐

