具有特定子节点的模板匹配节点 - 流式 XSLT

Template match nodes that have a particular child node - streaming XSLT

我想要 select 工作节点,它有一个计划子节点出现在 Addl_Information 部分

<xsl:mode streamable="yes"/>
<xsl:template match="Worker[Addl_Information/Plan]">

当我使用上面的代码时,我收到 Saxon-EE 9.6.0.5 处理器的错误提示

XTSE3430: Template rule is declared streamable but it does not satisfy the streamability rules. * The match pattern is not motionless

我做错了什么?

我在 w3c site 中看到了(类似的)静止模式的示例,但它对我不起作用,请指教。

更新:这是我的样式表。我试图只包括在他们的工人数据中有某个计划记录的人。请注意,下面的 patth 变量是我试图评估的另一个角度 - 基本上在剩余代码周围有一个 IF 条件。那也不行。

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:mode streamable="yes"/>
        <xsl:template match="Worker_Sync">
            <File>
                <xsl:apply-templates select="Worker"/>    
            </File>
        </xsl:template>

        <xsl:template match="Worker">
            <xsl:variable name="ThisPerson" select="copy-of()"/> 
            <xsl:variable name="patth" select="Additional_Information/ws:plan"/>
            <xsl:if test="$ThisPerson/$patth">
                <Row>
                    <A1_Account_Number><xsl:value-of select="$ThisPerson/Additional_Information/Account_Number"/></A1_Account_Number>
                    <A2_Employee_Number>...</A2_Employee_Number>
                </Row>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>

流式传输模式中的模板规则必须具有静止匹配模式。 "Motionless" 在此上下文中本质上意味着您可以在解析器位于元素开始标记处时评估模式。在这种情况下,您不能这样做,因为谓词测试是否存在 Addl_Information 子代和 Plan 孙代,如果不向前读取开始标记以外的内容,您将无法判断它们是否存在。

我很高兴从整体上看一下样式表,看看我是否可以提出任何使其可流式传输的建议,前提是它相当紧凑。

==稍后==

您可以使用遇到每个 Worker 元素时制作副本的方法,在这种情况下,您只需要在复制的元素内进行所有后续访问:

<xsl:variable name="ThisPerson" select="copy-of()"/> 
<xsl:if test="$ThisPerson/Additional_Information/ws:plan">
    <Row>
        <A1_Account_Number><xsl:value-of select="$ThisPerson/Additional_Information/Account_Number"/>   </A1_Account_Number>
        <A2_Employee_Number>...</A2_Employee_Number>
    </Row>
</xsl:if>

这可能是最简单的解决方案。可能有避免复制操作的方法(取决于确切的源文档结构),但它会更复杂,除非单个 Worker 元素非常大,否则不值得付出努力。

我建议使用

    <xsl:template match="Worker_Sync">
        <File>
            <xsl:apply-templates select="copy-of(Worker)[Addl_Information/Plan]" mode="some-non-streamable-mode"/>    
        </File>
    </xsl:template>

然后在 Worker 的模板中,您不需要测试,只需要

    <xsl:template match="Worker" mode="some-non-streamable-mode">
            <Row>
                <A1_Account_Number><xsl:value-of select="Additional_Information/Account_Number"/></A1_Account_Number>
                <A2_Employee_Number>...</A2_Employee_Number>
            </Row>
    </xsl:template>