1

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

我有以下构造:

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

2 回答 2

3

不幸的是,在 XSLT 1.0 中,当 xsl:variable 包含指令而不是选择属性时,结果始终是 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>
于 2012-03-23T17:18:46.120 回答
0

仅作记录,我在下面添加最终解决方案。它与 Michael 提出的略有不同,在应用模板之前将 RTF 的副本添加到变量中。
这是因为否则 MSXML 在 xsl 解析期间仍然会出错(显然它会检查应用模板选择值并得出结论,当它是 RTF 而不是节点集时它是不正确的。而且,正如迈克尔所说,xsl:variable 选择属性确实就是这样:将 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>
于 2012-03-23T17:52:55.560 回答