Maintaining Context in XSLT Functions
对于以下XML:
1 2 3 4 5 6 7 8 9 10 | <X12> <GROUP> <TS_850> <REF> <REF01>CR</REF01> <REF02>53222</REF02> </REF> </TS_850> </GROUP> </X12> |
此代码有效:
1 2 3 4 5 6 7 8 9 10 11 | <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"/> |
但是,此代码不:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <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 2 3 4 5 6 7 | <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> |
是-理论上(*)-此:
1 | <xsl:variable name="REF02" select="X12/GROUP/TS_850/REF[REF01 = 'CR']/REF02" /> |
(*),即每个
恰好有一个
关于您的功能,需要进行以下三个观察:
-
对于函数调用,当前节点不会更改。您可以放心地假设
. (或current() )在函数内部的含义与在函数外部的含义相同。您可以使用该事实隐式传输上下文。 - 在这个特定的函数中,您传入变量并且根本不引用上下文。所以无论如何当前节点都没关系。
-
通常,您可能希望使用
<xsl:sequence> 而不是<xsl:value-of> 作为返回值。序列比该函数将返回的纯字符串具有更多的通用性。
因此您的函数可能看起来像这样:
1 2 3 4 5 6 7 8 9 | <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> |
和这样的呼叫:
1 2 3 | <xsl:template match="X12/GROUP/TS_850/REF"> <xsl:copy-of select="test:valueWhereValue(REF01, 'CR', REF02)" /> </xsl:template> |
当您退后一步时,您的功能将替换为评分者复杂的内容:
1 2 3 4 5 | <xsl:template match="X12/GROUP/TS_850/REF"> <xsl:if test="REF01 = 'CR'"> <xsl:copy-of select="REF02" /> </xsl:if> </xsl:template> |
这又是一个相当复杂的说法:
1 2 3 | <xsl:template match="X12/GROUP/TS_850/REF[REF01 = 'CR']"> <xsl:copy-of select="REF02" /> </xsl:template> |
这又是一个相当复杂的说法:
1 | <xsl:copy-of select="X12/GROUP/TS_850/REF[REF01 = 'CR']/REF02" /> |
因此首先具有一个毫无意义的功能。