使用<xsl:choose> </xsl:choose>从结果树片段构建节点集变量

时间:2012-03-23 14:51:16

标签: xslt msxml node-set

是否可以使用xsl:choose从rtf创建节点集变量(用于MSXML引擎)?

我有以下结构:

<xsl:choose>
    <xsl:when test="function-available('msxsl:node-set')">
        <xsl:variable name="colorList" select="msxsl:node-set($std:colorList)"/>
        <xsl:for-each select="$colorList/color">
             tr.testid<xsl:value-of select="@testid"/> {
                color:<xsl:value-of select="."/>;
            }
       </xsl:for-each>
    </xsl:when>
    <xsl:otherwise>
        <xsl:variable name="colorList" select="$std:colorList"/>
        <xsl:for-each select="$colorList/color">
             tr.testid<xsl:value-of select="@testid"/> {
                color:<xsl:value-of select="."/>;
            }
       </xsl:for-each>
    </xsl:otherwise>
</xsl:choose>

std:colorList当然是树片段。 以上工作正常,并且没问题,因为两个备选方案的代码相同,但不是那么大 但是对于更大的代码片段,我想知道是否可以通过首先根据rtf声明变量来避免重复代码,然后执行代码;

之类的东西
<xsl:variable name="colorList">
    <xsl:choose>
        <xsl:when test="function-available('msxsl:node-set')">
            <xsl:copy-of select="msxsl:node-set($std:colorList)"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy-of select="$std:colorList"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

<xsl:for-each select="$colorList/color">
     tr.testid<xsl:value-of select="@testid"/> {
        color:<xsl:value-of select="."/>;
    }
</xsl:for-each>

但这不能正常工作:MSXML抱怨colorList不是节点集,因此无法在xsl:for-each中使用它。

XSL transformation failed due to following error:
Expression must evaluate to a node-set.
-->$colorList<--/color

请注意,在工作示例中,由于将std:colorList“复制”到colorList变量中,因此未发生此错误。显然它是一个xsl解析错误,而不是运行时错误 我应该使用除xsl:copy-of之外的其他内容吗?还是有另一种方法可以实现同样的目标吗?

如果您想知道,std:colorList内容如下:

<std:colorList>
    <color testid="111">#FF0000</color>
    <color testid="999">#FFFF00</color>
</std:colorList>

2 个答案:

答案 0 :(得分:3)

不幸的是,在XSLT 1.0中,当xsl:variable包含指令而不是select属性时,结果始终是RTF。因此,您将RTF转换为节点集的细致尝试将一事无成,因为它会再次直接转换回来。

我担心没有干净的解决方法(当然,除了转向XSLT 2.0)。我建议像这样构建代码:

<xsl:choose>
    <xsl:when test="function-available('msxsl:node-set')">
        <xsl:apply-templates select="msxsl:node-set($std:colorList)/color" mode="z"/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:apply-templates select="$std:colorList/color" mode="z"/>
    </xsl:otherwise>
</xsl:choose>

<xsl:template match="color" mode="z">
     tr.testid<xsl:value-of select="@testid"/> {
                color:<xsl:value-of select="."/>;
            }
</xsl:template>

答案 1 :(得分:0)

仅供记录,我在下面添加最终解决方案。它与迈克尔提出的略有不同,在应用模板之前将RTF的副本添加到变量中 这是因为否则MSXML在xsl解析期间仍然是错误的(显然它检查apply-templates选择值并且当它是RTF而不是节点集时结束它是不正确的。并且,正如迈克尔所说,xsl:variable select属性就是这样:将RTF转换为节点集。

<xsl:choose>
        <xsl:when test="function-available('msxsl:node-set')">
        <xsl:apply-templates select="msxsl:node-set($std:colorList)/color" mode="addTRclassToCSS"/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:variable name="colorList" select="$std:colorList"/>
        <xsl:apply-templates select="$colorList" mode="addTRclassToCSS"/>
    </xsl:otherwise>
</xsl:choose>


<xsl:template match="color" mode="addTRclassToCSS">
                tr.testid<xsl:value-of select="@testid"/> {
                color:<xsl:value-of select="."/>;
                }
</xsl:template>