Saxon XSLT处理器是否优化将隧道参数设置为其当前值?

时间:2017-04-21 17:05:15

标签: xml xslt xslt-2.0 saxon

我很好奇Saxon XSLT解析器是否会优化隧道参数传递 - 如果使用相同的值,是否重新创建?或者,它是否使用当前副本?

我不确定是否有必要提供一个示例,但我试图在下面说明我的特定用例。

示例输入xml:

<formDefinition sysid="1">
    <subform sysid="2">
        <subform layoutGrid="8" sysid="3">
            <field weight="2" sysid="4">
                <bind match="none" />
                <type><date /></type>
            </field>
        </subform>
    </subform>
</formDefinition>

提供一些上下文 - 子表单元素类似于HTML DIV元素,字段元素类似于HTML INPUT元素。 layoutGrid属性可以由子表单设置或覆盖,并由后代(如字段)使用。

我的实际样式表和'formDefinition'要大得多,使用许多隧道参数以及许多难以分区的相互关联设置,因此很难避免将参数重置为现有值。

我在下面尝试了一般性流程来说明我如何只设置其中一个隧道参数。

示例样式表 -

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[@sysid]">
    <xsl:apply-templates select="." mode="render" />
</xsl:template>

<xsl:template match="/formDefinition" mode="render">
    <xsl:copy>
         <xsl:next-match />
    </xsl:copy>
</xsl:template>

<xsl:template match="subform" mode="render">
    <xsl:param name="pLayoutGrid" as="xs:decimal" tunnel="yes" />
    <xsl:copy>
        <xsl:attribute name="effLayoutGrid" select="$pLayoutGrid" />
        <xsl:next-match />
    </xsl:copy>
</xsl:template>

<xsl:template match="field" mode="render">
   <xsl:param name="pLayoutGrid" as="xs:decimal" tunnel="yes" />
     <xsl:copy>
        <xsl:attribute name="effLayoutGrid" select="$pLayoutGrid" />
        <xsl:next-match />
    </xsl:copy>
</xsl:template>

<xsl:template match="*" mode="render">
    <xsl:apply-templates select="*[not(@sysid)]" />
    <xsl:call-template name="step" />
</xsl:template>

<xsl:template name="step">
    <xsl:apply-templates select="*[@sysid]">
        <xsl:with-param name="pLayoutGrid" as="xs:decimal" tunnel="yes">
            <xsl:apply-templates select="." mode="layoutGrid" />
        </xsl:with-param>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="/formDefinition" mode="layoutGrid">
    <xsl:sequence select="xs:decimal(12)" />  
</xsl:template>

<xsl:template match="subform" mode="layoutGrid">
    <xsl:param name="pLayoutGrid" as="xs:decimal" tunnel="yes" />
    <!-- potentially resetting the same value here -->
    <xsl:sequence select="(@layoutGrid, $pLayoutGrid)[1]" />  
</xsl:template>

<xsl:template match="field" mode="layoutGrid">
    <xsl:param name="pLayoutGrid" as="xs:decimal" tunnel="yes" />
    <!-- setting value to current value -->
    <xsl:sequence select="$pLayoutGrid" />  
</xsl:template>

</xsl:stylesheet>

输出:

<formDefinition>
    <subform effLayoutGrid="12">
        <subform effLayoutGrid="12">
            <field effLayoutGrid="8">
                <bind match="none" />
                <type>
                    <date />
                </type>
            </field>
        </subform>
    </subform>
</formDefinition>

我的问题,在示例的上下文中 - 确实重置pLayoutGrid隧道参数实际创建一个新的'对象',还是重新使用当前值,当值设置回其当前值时?

在我的完整代码中,我还有一些xml元素/树的隧道参数。我提到这个,因为我想知道'basic'类型和xml元素之间是否存在差异。

1 个答案:

答案 0 :(得分:2)

当Saxon调用模板时,它首先创建一个新的XPathContext对象;这对应于&#34;动态背景&#34;在XPath和XSLT规范中定义(除了在执行范围内不变的部分,例如当前日期/时间)。新的XPathContext对象复制调用者上下文的某些方面,并重新初始化其他部分(如局部变量)。

XPathContext对象包含一个名为tunnelParams的字段,其值为ParameterSet;这是一组名称/值对,而非HashMap。调用模板时,会创建一个新的ParameterSet对象,其中包含调用者传递的ParameterSet中的条目和被调用者声明的新隧道参数的并集。复制ParameterSet中的条目,但当然不需要复制值本身,因为所有XDM值都是不可变的。

话虽如此,我在理解你的问题究竟意味着什么方面有点麻烦。如果你&#34;重置&#34;作为现有值的隧道参数(例如,全局变量中的值),然后ParameterSet将包含对该值的引用。如果你使用一些计算设置它,比如

<xsl:with-param name="tun-par" select="23 to 50"/>

然后它不会认识到新值与之前的值相同。