oxygen的xslt断点常因执行环境不匹配而失效:默认内置saxon-he调试,若项目显式指定saxon9he.jar或使用外部处理器则调试器收不到事件;需检查验证场景中启用调试、避免html输出模式、禁用顶层表达式、正确处理上下文节点、确保xsl:message可见性,并清除缓存及重启调试会话。

为什么 oXygen 的 XSLT 断点经常不触发?
断点失效最常见原因是 XSLT 执行环境没对上——oXygen 默认用内置 Saxon-HE 调试,但如果你在项目里显式指定了 saxon9he.jar 或用了外部处理器(比如命令行调用 java -jar saxon.jar),调试器根本收不到事件。
- 检查
Document → Validate and Check → Configure Validation Scenario中的处理器是否勾选了Enable debugging - 确保 XSLT 文件顶部没有
<output method="html"></output>之类导致隐式切换输出模式的语句(某些旧版 Saxon 在 HTML 模式下会跳过调试钩子) - 避免在
<template match="/"></template>外直接写顶层表达式(如<value-of select="1+1"></value-of>),这类代码不会进入调试栈
如何在 for-each 和 apply-templates 中精准定位上下文节点?
调试时看到变量值是空,往往不是逻辑错,而是当前 XPath 上下文变了。Saxon 的调试视图默认只显示局部变量,不自动刷新 .(context item)或 current() 的实际节点。
- 在断点处右键 →
Evaluate XPath Expression,手动输入name(.)或string(@id)确认当前节点身份 - 把常用上下文信息提前绑定到变量里,例如:
<xsl:variable name="ctx-name" select="name(.)"/> <xsl:variable name="ctx-id" select="@id"/>
这样变量面板里能直接看到 - 慎用
for-each select="*"——它会丢失父节点信息;改用for-each select="child::node()"并配合parent::*显式追溯
oXygen 调试器看不到 xsl:message 输出?
xsl:message 默认被重定向到控制台,但调试模式下它可能被缓冲或丢弃,尤其当 terminate="no" 且后续模板抛异常时。
- 强制立即刷出:在
xsl:message后加terminate="yes"测试是否真执行到了(临时手段) - 改用
<message terminate="no"><value-of select="serialize(., map{'method': 'xml'})"></value-of></message>查看完整节点结构(需 Saxon 10+) - 如果用的是 Saxon-HE,
xsl:message不支持select属性,必须用<value-of></value-of>包裹,否则静默失败
修改 XSLT 后调试仍运行旧版本?
这是缓存陷阱。oXygen 会缓存已编译的样式表,尤其当你从外部路径(如 file:///C:/styles/common.xsl)导入时,哪怕源文件改了,调试器仍用内存里的旧字节码。
- 每次修改后按
Ctrl+Shift+F9(Windows)强制重新编译整个 XSLT 工程 - 关闭
Options → Preferences → XML / XSLT-FO-XQuery → XSLT → Use cached compiled stylesheets - 检查
Configure Validation Scenario中的 XSLT URL 是否是相对路径(如./transform.xsl)而非绝对路径,后者容易绕过文件监听
真正麻烦的是跨文档引用——比如主 XSLT 用 <import href="../lib/utils.xsl"></import>,改了 utils.xsl 却忘了重启调试会话,这时候连刷新都没用,必须关掉当前调试窗口重进。










