在XSLT函数中维护上下文

时间:2014-06-02 15:10:07

标签: xml xslt

对于以下XML:

<X12>
    <GROUP>
        <TS_850>
            <REF>
                <REF01>CR</REF01>
                <REF02>53222</REF02>
            </REF>
        </TS_850>
    </GROUP>
</X12>

此代码有效:

<xsl:variable name="REF02">
    <xsl:for-each select="X12/GROUP/TS_850/REF">
        <xsl:if test="REF01='CR'">
            <xsl:value-of select="REF02"/>
        </xsl:if>
    </xsl:for-each>
</xsl:variable>

...

<xsl:value-of select="$REF02"/>

但是,此代码不会:

<xsl:function name="test:valueWhereValue">
    <xsl:param name="context" />
    <xsl:param name="conditionalElement" />
    <xsl:param name="conditionalValue" />
    <xsl:param name="outputElement"/>

    <xsl:for-each select="$context">
        <xsl:if test="$conditionalElement = $conditionalValue">
            <xsl:value-of select="$outputElement" />
        </xsl:if>
    </xsl:for-each>
</xsl:function>

...

<xsl:copy-of select="test:valueWhereValue(X12/GROUP/TS_850/REF, REF01, 'CR', REF02)"></xsl:copy-of>

我可以说,两个代码片段在功能上应该是等效的。但是,根据我的调试器,REF01和REF02实际上并没有像我期望的那样在函数版本中引用节点。看起来我实际上没有用函数中的for-each语句输入正确的上下文,这会阻止子节点正确选择。为什么会这样,我该如何修复我的功能呢?

1 个答案:

答案 0 :(得分:2)

仅供参考,这:

<xsl:variable name="REF02">
    <xsl:for-each select="X12/GROUP/TS_850/REF">
        <xsl:if test="REF01='CR'">
            <xsl:value-of select="REF02"/>
        </xsl:if>
    </xsl:for-each>
</xsl:variable>

- 理论上(*) - 这个:

<xsl:variable name="REF02" select="X12/GROUP/TS_850/REF[REF01 = 'CR']/REF02" />

(*)即每REF01 只有'CR'等于TS_850

至于你的功能,有三个观察要做:

  • 当前节点不会因函数调用而改变。您可以放心地假设.(或current())在函数内部表示相同的内容,因为它意味着在外部。您可以使用该事实隐式地传输上下文。
  • 在此特定函数中,您传入变量并且根本不引用上下文。因此,无论如何,当前节点都无关紧要。
  • 通常,您可能希望使用<xsl:sequence>而不是<xsl:value-of>作为返回值。序列比函数原本返回的普通字符串更通用。

所以你的功能看起来更像是这样:

<xsl:function name="test:valueWhereValue">
    <xsl:param name="conditionalElement" />
    <xsl:param name="conditionalValue" />
    <xsl:param name="outputElement"/>

    <xsl:if test="$conditionalElement = $conditionalValue">
        <xsl:sequence select="$outputElement" />
    </xsl:for-each>
</xsl:function>

和这样的电话:

<xsl:template match="X12/GROUP/TS_850/REF">
    <xsl:copy-of select="test:valueWhereValue(REF01, 'CR', REF02)" />
</xsl:template>

当你退后一步时,你的功能是一个复杂的替代品:

<xsl:template match="X12/GROUP/TS_850/REF">
    <xsl:if test="REF01 = 'CR'">
        <xsl:copy-of select="REF02" />
    </xsl:if>
</xsl:template>

反过来说这是一种相当复杂的说法:

<xsl:template match="X12/GROUP/TS_850/REF[REF01 = 'CR']">
    <xsl:copy-of select="REF02" />
</xsl:template>

其中反过来是一种相当复杂的方式来说 this

<xsl:copy-of select="X12/GROUP/TS_850/REF[REF01 = 'CR']/REF02" />

所以它首先是一个毫无意义的功能。