tags:

views:

38

answers:

2

Hi,

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.

+1  A: 

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.

@user268396, thank you for your response. $var[] syntax does work. Here is an example. XSL: http://pastebin.com/iygKZ5ev ; XML: http://pastebin.com/AzFMiEHU ; Output: "States:Compound1Basic1Basic2Basic3Basic States:Basic1Basic2Basic3"Tested with xalan and xsltproc.
echo-flow
+1  A: 

Use this XPath one-liner:

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

Dimitre Novatchev
Works perfectly, thank you!
echo-flow