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

时间:2017-07-04 06:59:19

标签: xml xslt saxon xslt-3.0

我想选择在Addl_Information部分中出现Plan子节点的Worker节点

<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>

2 个答案:

答案 0 :(得分:0)

可流式模式中的模板规则必须具有静止匹配模式。 &#34;一动不动&#34;在这种情况下,本质上意味着您可以在解析器位于元素开始标记时评估模式。在这种情况下,您无法做到这一点,因为谓词会测试X孩子与Addl_Information孙子的存在情况,并且您无法判断这些是否存在而无需向前阅读开始标记。

我很高兴看一下整个样式表,看看我是否可以提出任何使其可流化的建议,只要它相当紧凑。

<强> == LATER ==

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

Plan

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

答案 1 :(得分:0)

我建议使用

    <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>