I'm trying to compare 2 lists and if there are 1 or more nodes that do not appear in the other list I want to output a single node in the resulting xml.
Example XML:
<Root>
<Layers>
<List1>
<Name>test1</Name>
<Name>test2</Name>
<Name>test3</Name>
</List1>
</Layers>
<MoreLayers>
<List2>
<Name>test1</Name>
<Name>test4</Name>
<Name>test5</Name>
</List2>
</MoreLayers>
</Root>
Which should see that test2 and test3 don't appear in List2 and give the following output:
<RootOut>
<UniqueNames>Yes</UniqueNames>
</RootOut>
I've tried using a for-each loop on List1 and doing a key comparison with List2, but this ends up creating 1 node per unique name, so would output 2 <UniqueNames>Yes</UniqueNames>
nodes in the output. I'm sure there's something easy I'm missing, but I can't figure it out.
XSLT:
<xsl:variable name="list1_names" select="/Root/Layers/List1/Name"/>
<xsl:key name="list2_lookup" match="/Root/MoreLayers/List2" use="Name"/>
<xsl:template match="/*">
<RootOut>
<xsl:call-template name="UniqueNames" />
</policy>
</xsl:template>
<xsl:template name="UniqueNames">
<xsl:for-each select="$list1_names">
<xsl:if test="(not(key( 'list2_lookup', Name )))">
<UniqueNames>Yes</UniqueNames>
</xsl:if>
</xsl:for-each>
</xsl:template>
CodePudding user response:
How about simply:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="list2" match="List2/Name" use="." />
<xsl:template match="/Root">
<RootOut>
<xsl:if test="Layers/List1/Name[not(key('list2', .))]">
<UniqueNames>Yes</UniqueNames>
</xsl:if>
</RootOut>
</xsl:template>
</xsl:stylesheet>
Note that this only tests if there are Name
s in List1
that do not appear in List2
, not the other way round (your description is somewhat vague on this point).
Another option is to look at it from the opposite direction:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="list1" match="List1/Name" use="." />
<xsl:template match="/Root">
<RootOut>
<xsl:if test="count(Layers/List1/Name) > count(key('list1', MoreLayers/List2/Name))">
<UniqueNames>Yes</UniqueNames>
</xsl:if>
</RootOut>
</xsl:template>
</xsl:stylesheet>