Saxon-JS中fn:document()遇404触发报错,能否配置恢复旧版XSLT的兼容行为?
解决Saxon-JS中fn:document()遇404报错的向后兼容方案
好问题!首先得明确:目前Saxon-JS并没有提供直接的配置选项,让fn:document()回到旧版遇到404不报错的行为——因为它是严格遵循XSLT 3.0规范实现的,而规范里明确doc()/document()在无法加载资源时允许抛出动态错误,你之前用的旧版本处理器(比如Saxon 8.1.1、浏览器内置处理器)属于宽松实现,没有严格执行这条规则。
不过我们可以通过代码层面的兼容处理,既让Saxon-JS不抛出异常,又保留对XSLT 1.0/2.0环境的向后兼容性,这里有两种可靠的方案:
方案1:基于function-available()的条件判断(推荐)
自定义一个兼容函数,先检测当前环境是否支持fn:doc-available(XSLT 3.0及以上环境支持),再选择对应的处理逻辑:
<xsl:function name="my:load-document" as="document-node()?"> <xsl:param name="uri" as="xs:string"/> <xsl:choose> <!-- 针对支持doc-available的环境(如Saxon-JS),先判断文档是否可用 --> <xsl:when test="function-available('fn:doc-available')"> <xsl:if test="doc-available($uri)"> <xsl:sequence select="doc($uri)"/> </xsl:if> </xsl:when> <!-- 针对旧环境(XSLT 1.0/2.0),直接调用document(),依赖旧处理器的宽松行为 --> <xsl:otherwise> <xsl:sequence select="document($uri)"/> </xsl:otherwise> </xsl:choose> </xsl:function>
之后你只需要把代码中所有的document($uri)调用替换成my:load-document($uri)即可:
- 在Saxon-JS环境中,会先通过
doc-available()检查资源是否存在,避免加载失败抛出异常; - 在旧版处理器中,依然保持原来的
document()调用逻辑,不会出现兼容性问题。
方案2:利用XSLT 3.0的try/catch块
如果你的代码已经部分使用XSLT 3.0特性,也可以用try/catch捕获加载异常,但同样需要通过条件判断兼容旧环境:
<xsl:function name="my:load-document" as="document-node()?"> <xsl:param name="uri" as="xs:string"/> <xsl:choose> <!-- 针对XSLT 3.0环境(如Saxon-JS),用try/catch捕获异常 --> <xsl:when test="function-available('fn:doc') and xs:version() >= 3.0"> <xsl:try> <xsl:sequence select="doc($uri)"/> <xsl:catch select="()"/> <!-- 加载失败时返回空序列 --> </xsl:try> </xsl:when> <!-- 旧环境继续使用document() --> <xsl:otherwise> <xsl:sequence select="document($uri)"/> </xsl:otherwise> </xsl:choose> </xsl:function>
这个方案的核心是在Saxon-JS中捕获加载失败的异常,返回空序列;旧环境则不受影响。
补充说明
之所以没有直接的配置开关,是因为Saxon-JS的设计目标是严格实现XSLT 3.0和XPath 3.1规范,而旧版处理器的宽松行为其实是不符合规范的。通过自定义兼容函数的方式,既能符合新规范的要求,又能兼顾旧环境的兼容性,是目前最稳妥的解决方式。
内容的提问来源于stack exchange,提问作者Gunther Schadow
相关产品推荐
相关产品推荐

