如何根据另一个节点列表的内容过滤节点列表

时间:2010-06-08 02:37:06

标签: xslt

我想使用XSLT根据另一个节点列表的内容过滤节点列表。具体来说,我想过滤一个节点列表,以便从结果节点列表中删除具有相同id属性的元素。应优先考虑两个节点列表中的一个。

我最初想象实现这个的方式是做这样的事情:

<xsl:variable name="filteredList1" select="$list1[not($list2[@id_from_list1 = @id_from_list2])]"/>

问题是上下文节点在$ list2的谓词中发生了变化,因此我无法访问属性@ id_from_list1。由于这些范围限制,我不清楚如何使用嵌套谓词以这种方式从外部节点列表引用属性。

为了解决上下文节点的问题,我尝试创建一个涉及for-each循环的解决方案,如下所示:

    <xsl:variable name="filteredList1"> 
        <xsl:for-each select="$list1">
            <xsl:variable name="id_from_list1" select="@id_from_list1"/>

            <xsl:if test="not($list2[@id_from_list2 = $id_from_list1])">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>

但这不能正常工作。我也不清楚它是如何失败的......使用上述技术,filteredList1的长度为1,但似乎是空的。这是一种奇怪的行为,无论如何,我觉得必须有更优雅的方法。

我很感激任何人都可以提供任何指导。感谢。

2 个答案:

答案 0 :(得分:4)

使用此XPath单行

<强> $vList1[not(@id = $vList2/@id)]

答案 1 :(得分:1)

据我所知,使用$ var []语法不起作用。有效的是:expr1 / [expr2 = $ var]和func1($ var)。

你可以做的只是嵌入在if测试中产生$ list2的表达式:

<xsl:for-each select="$list1">
  <xsl:variable name="id" select="@id_from_list1"/>
  <xsl:if test="not(expr2[@id_from_list2 = $id ])">
    <xsl:copy-of select="."/>
  </xsl:if>
</xsl:for-each>
<xsl:copy-of select="$list2"/>

用实际表达式替换expr2。