You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT1.0中经str:replace处理的变量传入key()返回false是何原因?

问题根因

你遇到的问题和key()、str:replace()本身的功能缺陷无关,核心是XSLT 1.0中key()函数的查询上下文规则导致的:
key()函数默认会在「当前上下文节点所属的文档」中匹配节点,你在遍历$fruits-list的时候,上下文节点已经切换到了local-namespace.xsl文档里的lcl:fruit节点,此时调用key()会去local-namespace.xsl里查找匹配项,而你的fruitsKey是定义在源文件fruits.xml的结构上的,自然查不到结果。


疑问解答

  1. XSLT1.0的key()函数是否存在相关缺陷?
    不存在,这是符合规范的设计。XSLT 1.0的key()始终绑定当前上下文所属的文档,当处理多文档(比如你这里用document('')读取了当前XSL文件本身作为额外数据源)时,切换上下文节点就会切换key()的查询目标文档。

  2. str:replace()是否会对返回值产生未预见的变更?
    不会。你打印的结果已经验证替换后的字符串和预期完全一致,问题和字符串替换过程没有任何关系。

  3. 有什么方法可以定位该问题的原因?
    可以通过以下两个方向排查:

  • 排除替换逻辑的影响:直接把固定值'fresh-apple'赋值给$selector再调用key(),如果仍然返回false,就可以确认问题和替换逻辑无关。
  • 打印当前上下文信息:在调用key()前输出base-uri(.)(当前节点所属文档的路径)、name(.)(当前节点名称),就能发现此时上下文已经不在fruits.xml中。

修复方案

只需要在调用key()时把上下文切回源文档fruits.xml即可,修改代码如下:

  1. 先在遍历$fruits-list前存储源文档的根节点:
<xsl:template match="fruits/fruit-selector">
    <xsl:variable name="currentfruitElement" select="."/>
    <!-- 存储源文档根节点,后续用来切换上下文 -->
    <xsl:variable name="source-root" select="/"/>
    <xsl:for-each select="$fruits-list">
        <xsl:call-template name="CheckFruits">
            <xsl:with-param name="fruitElement" select="$currentfruitElement"/>
            <xsl:with-param name="currentFruit" select="."/>
            <!-- 把源文档根节点作为参数传入 -->
            <xsl:with-param name="source-root" select="$source-root"/>
        </xsl:call-template>
    </xsl:for-each>
</xsl:template>
  1. 在CheckFruits模板中切换上下文后再调用key():
<xsl:template name="CheckFruits">
    <xsl:param name="fruitElement"/>
    <xsl:param name="currentFruit"/>
    <xsl:param name="source-root"/>
    <xsl:variable name="selector" select="str:replace($fruitElement, '${FRUIT-NAME}', string($currentFruit))"/>
    <!-- 切换上下文到源文档,再调用key -->
    <xsl:for-each select="$source-root">
        <xsl:if test="not(key('fruitsKey', $selector))">
            <Error><xsl:value-of select="concat('Fruit element: ', $selector, ' is not available')"/></Error>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

修改后执行就不会再误报错误了。


涉及核心概念补充

  • 上下文节点:XSLT处理过程中当前正在操作的节点,所有相对路径查询、上下文相关函数(比如key()、current())的行为都依赖这个节点。
  • 多文档处理上下文切换:当你用document()函数读取其他XML/XSL文件作为数据源时,只要选中了其他文档的节点作为当前上下文,后续的查询默认都会指向那个文档,需要主动切换回原文档才能操作原文档的节点。

内容的提问来源于stack exchange,提问作者DonBaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 03:51:03