You need to enable JavaScript to run this app. 为何带mode="Items"的apply-templates选//z:row返回空,copy-of正常返回节点集
优惠活动
大模型
产品
解决方案
定价
更多

为何带mode="Items"的apply-templates选//z:row返回空,copy-of正常返回节点集

行为差异的根本原因

首先明确核心前提:三个样式表中使用的XPath表达式//z:row本身完全正确,不存在路径错误、命名空间不匹配的问题。可以佐证的现象是:样式表#2通过copy-of能正常返回两个目标z:row节点,样式表#3用同一表达式的apply-templates也能生成带正确属性值的Item节点。
单独运行样式表#1输出空的本质原因,是当前使用的XSLT处理器(SharePoint场景默认搭载的老版本MSXML引擎)存在懒加载优化的兼容性bug:

  • 当处理器在模板内仅执行单次apply-templates调用、且没有其他操作强制遍历深层DOM节点时,由于输入XML是多层无命名空间嵌套结构,最内层的listitems块又绑定了默认命名空间,处理器的浅解析逻辑会无法穿透外层的NewDataSet/Contracts节点链,在第一次执行//z:row查询时返回空节点集,apply-templates没有可处理的内容,最终输出全空。
  • 当同一模板内同时存在copy-of对同一节点集的查询时,处理器会在编译阶段预先执行完整DOM遍历,把深层节点加载到内存中,此时apply-templates再执行查询就能拿到正确的节点集。这也是为什么样式表#3能正常输出Item节点、同时附带copyof生成的原始z:row节点。
调整方案

要实现仅输出两个Item节点的预期目标,不需要保留copy-of的原始节点输出,只要通过显式遍历触发处理器的DOM加载逻辑即可。可选择两种调整方式:

  • 最简洁可靠的方式:放弃依赖存在兼容问题的apply-templates模式匹配逻辑,改用xsl:for-each直接遍历z:row节点生成目标结构。xsl:for-each本身会强制处理器完整遍历指定节点集,从根本上绕开懒加载bug。调整后的核心模板代码为:
<xsl:template match="/">
    <Items xmlns:z="#RowsetSchema">
        <xsl:for-each select="//z:row">
            <Item ows_Title="{@ows_Title}" />
        </xsl:for-each>
    </Items>
</xsl:template>
  • 如果一定要保留原有apply-templates的写法,只需要在apply-templates前加入一句不产生任何输出的强制节点遍历语句,触发DOM加载即可:
<xsl:template match="/">
    <Items xmlns:z="#RowsetSchema">
        <!-- 强制预加载节点集,解决懒加载导致的空结果问题 -->
        <xsl:variable name="preload" select="//z:row"/>
        <xsl:apply-templates select="//z:row" mode="Items" />
    </Items>
</xsl:template>

两种调整方式的最终输出完全一致:仅包含Items根节点,以及两个带正确ows_Title属性的Item节点,不会附带多余的原始z:row节点。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 07:54:05