在 Streaming XSLT 中使用同一个节点两次

Consuming the same node twice in Streaming XSLT

我正在尝试将某些 XML 转换为 XSLT 3.0 中指定的插页式 JSON 表示(稍后通过 xml-to-json 转换为 JSON)。我当前的 XSLT 作为非流式样式表运行良好,但我 运行 在转换为流式的过程中遇到了问题。具体来说,在某些情况下我需要使用相同的节点两次,特别是在 XML 中重复标记的情况下,我正在将其转换为等效的 JSON 表示形式的数组。

<xsl:if test="boolean(cdf:AdjudicatorName)">
    <array key="AdjudicatorName">
        <xsl:for-each select="cdf:AdjudicatorName">
            <string>
                <xsl:value-of select="."/>
            </string>
        </xsl:for-each>
    </array>
</xsl:if>

boolean(cdf:AdjudicatorName) 测试标签是否存在,如果存在则创建一个数组。

此代码在 Oxygen (Saxon-EE) 中失败并显示以下消息

Template rule is declared streamable but it does not satisfy the streamability rules. * There is more than one consuming operand: {fn:exists(...)} on line {X}, and {<string {(attr{key=...}, ...)}/>} on line {Y}

我知道 copy-of 解决方法,但是,源文件中的许多项目可以在最高级别重复,因此使用这种方法可以节省最少的内存。

这看起来是 xsl:where-populated 的完美用例:

<xsl:where-populated>
    <array key="AdjudicatorName">
        <xsl:for-each select="cdf:AdjudicatorName">
            <string>
                <xsl:value-of select="."/>
            </string>
        </xsl:for-each>
    </array>
</xsl:where-populated>

xsl:where-populated 指令(正是为此目的而发明)对其 child 指令进行逻辑评估,然后消除结果序列中的任何项目 "deemed empty",其中如果元素没有 children,则元素被认为是空的。在流式实现中,开始标记 (<array>) 将是 "held back" 直到它的第一个 child 被生成,并且当相应的结束标记 (</array>) 被发出时,对如果没有干预 children 发出,将丢弃的标签。