XSL存储在变量中的节点集

时间:2011-03-14 18:07:24

标签: xslt

(XSLT 1.0。) 给定一个名为Rows的变量,其中包含以下(示例):

输入

<AllResults>
    <Result>
      <subject>can be filtered by filter 1</subject>
      <type>can be filtered by filter 2</type>
      <date>can be filtered by filter 3</date>
    </Result>
    <Result> ...
    </Result>
</AllResults>

我有3个过滤变量。对于每个过滤器,如果过滤器变量不为空,我想将过滤器应用于上面显示的输入。我想将过滤后的结果(与过滤器匹配的项)存储到一个新变量中。我尝试了以下内容,但是我收到一条关于它的错误消息(filterResult)是“结果树而不是节点集”。 Rows变量是一个节点集,正如我通过使用调试器确定的那样。

XSL的一部分

<xsl:variable name="filterResult">
    <xsl:choose>
        <xsl:when test="$filter1 != '' and $filter2 != '' and $filter3 != ''">
            <xsl:copy-of select="$Rows[date=$filter1 and type=$filter2 and subject=$filter3]" />
        </xsl:when>
        <xsl:when test="$filter1 != '' and $filter2 != ''">
            <xsl:copy-of select="$Rows[date=$filter1 and type=$filter2]" />
        </xsl:when>
        <xsl:when test="$filter1 != '' and $filter3 != ''">
            <xsl:copy-of select="$Rows[date=$filter1 and subject=$filter3]" />
        </xsl:when>
        <xsl:when test="$filter3 != '' and $filter2 != ''">
            <xsl:copy-of select="$Rows[type=$filter2 and subject=$filter3]" />
        </xsl:when>
        <xsl:when test="$filter1 != ''">
            <xsl:copy-of select="$Rows[date=$filter1]" />
        </xsl:when>
        <xsl:when test="$filter3 != ''">
            <xsl:copy-of select="$Rows[subject=$filter3]" />
        </xsl:when>
        <xsl:when test="$filter2 != ''">
            <xsl:copy-of select="$Rows[type=$filter2]" />
        </xsl:when>
        <xsl:otherwise> 
            <xsl:copy-of select="$Rows" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

我意识到copy-of产生了一个结果树,而不是一个节点集,但我不确定如何根据我上面描述的3个过滤器要求生成一个节点集。

其他信息

我知道我可以做<xsl:variable name="me" select="/set/node"/>之类的东西,它会创建一个包含节点集的变量,但我看不出这对我有什么帮助,因为我有很多可能的条件(给定三个过滤器) )。

2 个答案:

答案 0 :(得分:11)

在XSLT 1.0中,创建包含源文档中的一组节点的变量的唯一方法是通过评估select属性中的XPath表达式:

<xsl:variable name="name" select="xpath_expression"/>

您无法使用copy-ofapply-templatescall-template;这些都将产生结果树片段。

我所知道的每个XSLT处理器都实现了一个扩展函数,可以将结果树片段转换为节点集,因此,除非您需要将转换完全跨平台,否则可以执行以下操作(此示例使用Microsoft的XSLT处理器) ):

<xsl:variable name="filterResultNodeSet" select="msxsl:node-set($filterResult)"/>

但是你甚至不需要这样做:正如Alejandro指出的那样,只需编写一个XPath表达式就可以得到你正在寻找的结果。有些应用程序的节点选择非常复杂,你必须使用node-set()函数,但你的不是其中之一。

答案 1 :(得分:7)

看起来$Rows变量是Result Tree Fragment类型的实例。

除了字符串操作之外,您无法在RTF上执行任何操作(如[]过滤器表达式提供的操作):来自http://www.w3.org/TR/xslt#section-Result-Tree-Fragments

  

允许对结果进行操作   树片段仅在该操作时   将被允许​​在一个字符串(   对字符串的操作可能涉及   首先将字符串转换为   数字或布尔值)。特别是它   不允许使用///,   和结果树上的[]运算符   片段。

除此之外,如果$Rows是节点集数据类型的实例,则所有显示的代码都可以简化:

<xsl:variable name="filterResult" 
              select="$Rows[(date=$filter1 or $filter1='')
                               and 
                            (type=$filter2 or $filter2='')
                               and 
                            (subject=$filter3 or $filter3='')]"/>

有XSLT处理器(主要是每一个)为RTF到节点集转换提供node-set()扩展功能的实现。