XSL 将节点集存储在变量中

问题描述 投票:0回答:2

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

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

附加信息

我确实知道我可以做类似

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

xslt
2个回答
12
投票

在 XSLT 1.0 中,创建包含源文档中的一组节点的变量的唯一方法是计算

select
属性中的 XPath 表达式:

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

您不能使用

copy-of
apply-templates
call-template
;这些都会产生一个结果树片段。

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

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

但您甚至不需要这样做:正如 Alejandro 所指出的,您只需编写一个 XPath 表达式即可获得您正在寻找的结果。有些应用程序的节点选择非常复杂,您必须使用

node-set()
函数,但您的不是其中之一。


8
投票

看起来

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

除了字符串操作之外,您不能对 RTF 执行任何操作(如

[]
过滤表达式提供的操作):来自 https://www.w3.org/TR/xslt-10/#section-Result-树碎片

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

/
//
、 结果树上的 和
[]
运算符 碎片。

除此之外,如果

$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()
扩展功能的实现。

© www.soinside.com 2019 - 2024. All rights reserved.