[Adam van den Hoven]
I have a node set that looks something like:
<branch>
<service servId="Service 1" />
<service servId="Service 3" />
<service servId="Service 4" />
</branch>
[snipped]
Now what I want is a set of all the service elements that do
not appear in ALL the branch Elements. In this case I'm hoping for
<service servId="Service 3" />
<service servId="Service 2" />
<service servId="Service 3" />
You cannot compare each servId with the set of unique servId values,
since there would always be a match. So you have to check each unique
value in turn to see if it is present in the branch.
Here is a fairly simple way to do this. Yes, it does use a key - to
create the set of unique servId values - and yes, it does use
xsl:for-each - to check each of those unique values.
First the result, then the stylsheet -
=========== result ============
<results>
<branch>missing: Service 2</branch>
<branch>missing: Service 3</branch>
<branch>missing: Service 2</branch>
</results>
=============== Stylesheet =============
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding='iso-8859-1'/>
<xsl:key name='services' match='service' use='@servId'/>
<xsl:variable name='services' select='/root/branch/service'/>
<xsl:variable name='unique-services'
select='$services[generate-id(.) =
generate-id(key("services",@servId))]'/>
<xsl:variable name='unique-service-ids'
select='$unique-services/@servId'/>
<xsl:template match="/root">
<results>
<xsl:apply-templates select='branch'/>
</results>
</xsl:template>
<xsl:template match='branch'>
<xsl:variable name='servs' select='service/@servId'/>
<branch>
<xsl:for-each select='$unique-service-ids'>
<xsl:if test='not(. = $servs)'>missing:
<xsl:value-of select='.'/></xsl:if>
</xsl:for-each>
</branch>
</xsl:template>
</xsl:stylesheet>
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list