Saxon9:如何从XPathContext获取所有已声明的XSL变量
获取Saxon XPathContext中所有可用变量的方案
要枚举当前上下文的所有可用变量(包括局部变量和全局变量),需要结合遍历上下文调用栈和全局变量集合,以下是具体实现步骤:
1. 遍历上下文栈获取局部变量
Saxon的XPathContext采用链式结构,每个栈帧对应一个局部作用域(比如模板、循环、条件块内的变量)。通过getCaller()可以向上遍历所有外层上下文,每个上下文的getStackFrameMap()返回变量定义的SlotManager,getLocalStackFrame()返回变量值数组。
示例代码:
XPathContext currentCtx = context; while (currentCtx != null) { SlotManager slotManager = currentCtx.getStackFrameMap(); Sequence[] localVars = currentCtx.getLocalStackFrame(); if (slotManager != null && localVars != null) { int varCount = slotManager.getNumberOfVariables(); for (int i = 0; i < varCount; i++) { StructuredQName varName = slotManager.getVariableName(i); Sequence varValue = localVars[i]; if (varName != null) { // 输出变量信息,可根据需求替换为自定义逻辑 System.out.printf("局部变量:%s = %s%n", varName.getDisplayName(), varValue.getStringValue()); } } } currentCtx = currentCtx.getCaller(); }
2. 合并全局变量与局部变量
局部变量会覆盖同名的全局变量,因此先收集全局变量,再用遍历到的局部变量覆盖同名项,得到当前上下文的最终可用变量集合:
// 初始化全局变量集合 Map<StructuredQName, Sequence> allAvailableVars = new HashMap<>(); CompiledGlobalVariables globalVars = context.getController().getExecutable().getCompiledGlobalVariables(); if (globalVars != null) { for (StructuredQName varName : globalVars.getVariableNames()) { allAvailableVars.put(varName, globalVars.getVariable(varName)); } } // 遍历局部变量,覆盖全局同名变量 XPathContext currentCtx = context; while (currentCtx != null) { SlotManager slotManager = currentCtx.getStackFrameMap(); Sequence[] localVars = currentCtx.getLocalStackFrame(); if (slotManager != null && localVars != null) { int varCount = slotManager.getNumberOfVariables(); for (int i = 0; i < varCount; i++) { StructuredQName varName = slotManager.getVariableName(i); Sequence varValue = localVars[i]; if (varName != null) { allAvailableVars.put(varName, varValue); } } } currentCtx = currentCtx.getCaller(); } // allAvailableVars 即为当前上下文所有可用变量的集合
3. 关键注意事项
- 匿名变量(如未命名的循环位置变量)的
varName会返回null,需根据业务场景决定是否处理这类变量。 - 不同Saxon版本(HE/PE/EE)的API可能存在细微差异,请确保代码与使用的Saxon版本兼容。
- 变量值为
Sequence类型,可根据实际需求转换为具体类型(如AtomicSequence、NodeInfo等)。
内容的提问来源于stack exchange,提问作者martin
相关产品推荐
相关产品推荐

