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

XSLT 3.0流处理模板规则不可流化问题求助

解决SAXON流处理中模板不可流化的问题

问题根源

流处理模式下,同一个流节点只能被消费一次。你的代码中同时存在「检查是否存在item」和「遍历item」两个操作,相当于两次消费流;另外直接返回流节点的遍历结果也不符合流处理规则,最终触发Template rule is not streamable错误。

修复方案

使用SAXON支持的xsl:fork指令(XSLT 3.0特性),将「检查item是否存在」和「遍历item」的操作拆分到独立分支,避免重复消费流;同时确保输出为原子文本值,而非流节点。

修正后的XSLT代码

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="UTF-8"/>
    <xsl:mode streamable="yes"/>

    <xsl:template match="/root">
        <xsl:fork>
            <!-- 分支1:无item时输出默认行 -->
            <xsl:sequence>
                <xsl:if test="not(exists(item))">
                    <xsl:text>default_id,default_name,default_value&#10;</xsl:text>
                </xsl:if>
            </xsl:sequence>
            <!-- 分支2:遍历item输出对应行 -->
            <xsl:sequence>
                <xsl:for-each select="item">
                    <xsl:value-of select="concat(id, ',', name, ',', value, '&#10;')"/>
                </xsl:for-each>
            </xsl:sequence>
        </xsl:fork>
    </xsl:template>
</xsl:stylesheet>

关键说明

  1. xsl:fork会复制输入流到多个分支,每个分支可独立消费流,规避重复读取的问题。
  2. 所有输出都通过xsl:text或concat转换为字符串原子值,符合流处理对结果的要求。
  3. 保留xsl:mode streamable="yes"开启流处理模式。

示例验证

含item的XML输入

<root>
    <item>
        <id>1</id>
        <name>test1</name>
        <value>val1</value>
    </item>
    <item>
        <id>2</id>
        <name>test2</name>
        <value>val2</value>
    </item>
</root>

输出结果:

1,test1,val1
2,test2,val2

不含item的XML输入

<root>
    <!-- 无item元素 -->
</root>

输出结果:

default_id,default_name,default_value

备选方案(不依赖xsl:fork)

若无法使用xsl:fork,可先将item节点加载到内存变量(注意大体积XML可能占用较多内存),再进行判断:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="UTF-8"/>
    <xsl:mode streamable="yes"/>

    <xsl:template match="/root">
        <xsl:variable name="items" select="item" as="node()*"/>
        <xsl:choose>
            <xsl:when test="not($items)">
                <xsl:text>default_id,default_name,default_value&#10;</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:for-each select="$items">
                    <xsl:value-of select="concat(id, ',', name, ',', value, '&#10;')"/>
                </xsl:for-each>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:01:18