I'd like to use XSLT to filter a node list based on the contents of another node list. Specifically, I'd like to filter a node list such that elements with identical id attributes are eliminated from the resulting node list. Priority should be given to one of the two node lists.
The way I originally imagined implementing this was to do something like this:
<xsl:variable name="filteredList1" select="$list1[not($list2[@id_from_list1 = @id_from_list2])]"/>
The problem is that the context node changes in the predicate for $list2, so I don't have access to attribute @id_from_list1. Due to these scoping constraints, it's not clear to me how I would be able to refer 开发者_高级运维to an attribute from the outer node list using nested predicates in this fashion.
To get around the issue of the context node, I've tried to create a solution involving a for-each loop, like the following:
<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>
But this doesn't work correctly. It's also not clear to me how it fails... Using the above technique, filteredList1 has a length of 1, but appears to be empty. It's strange behaviour, and anyhow, I feel there must be a more elegant approach.
I'd appreciate any guidance anyone can offer. Thanks.
Use this XPath one-liner:
$vList1[not(@id = $vList2/@id)]
As far as I am aware using $var[] syntax doesn't work. What works is: expr1/[expr2 = $var], and func1($var).
What you can do is simply embed the expression that yields $list2 in the if test:
<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"/>
Substitute expr2 with actual expression.
精彩评论