Search code examples
xslt

XSLT to iterate between 2 variables and produce new variable


I have two variables that look like

        <xsl:variable name="A">
            <asset id="111">[...]</asset>
            <asset id="222">[...]</asset>
        </xsl:variable>

        <xsl:variable name="B">
            <asset id="333">[...]</asset>
            <asset id="444">[...]</asset>
            <asset id="111">[...]</asset>
            <asset id="555">[...]</asset>
            <asset id="999">[...]</asset>
        </xsl:variable>

I wish to take each ID value of A and check to see if it is NOT found in B. If it is NOT found, copy the current node from A into the new variable.

        <xsl:variable name="Final">
            <xsl:for-each select="$A/asset">
                <xsl:variable name="presentXML">
                    <xsl:copy-of select="."/>
                </xsl:variable>
                <xsl:variable name="presentID">
                    <xsl:value-of select="./@id"/>
                </xsl:variable>

                <xsl:for-each select="$B/asset">
                    <xsl:variable name="pastID">
                        <xsl:value-of select="./@id"/>
                    </xsl:variable>

                    <xsl:choose>
                        <xsl:when test="$presentID != $pastID">
                            <xsl:copy-of select="$presentXML"/>
                        </xsl:when>
                        <xsl:otherwise>

                        </xsl:otherwise >
                    </xsl:choose>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:variable>

If the code above worked, only [...] would be added to variable Final. I cannot come up with a way to properly test in <xsl:when test="$presentID != $pastID"> to produce this result. I understand why that doesn't work properly, but can someone say how I could go about this?


Solution

  • XSLT is a functional language. There is no need to iterate. You can do simply:

    <xsl:copy-of select="$A/asset[not(@id=$B/asset/@id)]"/>
    

    (Provided your processor supports XSLT 2.0 or higher. Otherwise you will need to convert the variables to a node-set first.)


    Do note that:

    [not(@id=$B/asset/@id)]
    

    is not the same thing as:

    [@id!=$B/asset/@id]
    

    The latter is true when there is at least one id in $B that is not equal to the current id (and therefore it will be true for any id from $A, as long as there are at least two different ids in $B.