Performing Set Operations When Querying XML - XSLT 2.0 Enhancements
(Page 3 of 4 )
The main enhancement of XSLT 2.0 is to take advantage of the availability of first-class functions and sequences. This eliminates the need for recursion, the call-back trick, and leads to cleaner definitions and usage. The functions vset:element-equality and vset:member-ofcan still be overridden in importing stylesheets to customize behavior.
<!-- The default implementation of element equality. Override in the importing stylesheet as necessary. --> <xsl:function name="vset:element-equality" as="xs:boolean"> <xsl:param name="item1" as="item()?"/> <xsl:param name="item2" as="item()?"/> <xsl:sequence select="$item1 = $item2"/> </xsl:function>
<!-- The default set membership test uses element equality. You will rarely need to override this in the importing stylesheet. --> <xsl:function name="vset:member-of" as="xs:boolean"> <xsl:param name="set" as="item()*"/> <xsl:param name="elem" as="item()"/> <xsl:variable name="member-of" as="xs:boolean*" select="for $test in $set return if (vset:element-equality($test, $elem)) then true() else ()"/> <xsl:sequence select="not(empty($member-of))"/> </xsl:function>
<!-- Compute the union of two sets using "by value" equality. --> <xsl:function name="vset:union" as="item()*"> <xsl:param name="nodes1" as="item()*" /> <xsl:param name="nodes2" as="item()*" /> <xsl:sequence select="$nodes1, for $test in $nodes2 return if (vset:member-of($nodes1,$test)) then () else $test"/> </xsl:function>
<!-- Compute the intersection of two sets using "by value" equality. --> <xsl:function name="vset:intersection" as="item()*"> <xsl:param name="nodes1" as="item()*" /> <xsl:param name="nodes2" as="item()*" /> <xsl:sequence select="for $test in $nodes1 return if (vset:member-of($nodes2,$test)) then $test else ()"/> </xsl:function>
<!-- Compute the difference between two sets (node1 - nodes2) using "by value" equality. -->
<xsl:function name="vset:difference" as="item()*"> <xsl:param name="nodes1" as="item()*" /> <xsl:param name="nodes2" as="item()*" /> <xsl:sequence select="for $test in $nodes1 return if (vset:member-of($nodes2,$test)) then () else $test"/> </xsl:function>