Reputation: 820
I have existing code to get a unique list of values for a given type of node, but now I want to do something special if any node with a particular value has a specific attribute.
Sample XML:
<TopNode>
<SampleNode>
<Widget Special="True">Widget1</Widget>
<Widget>Widget2</Widget>
</SampleNode>
<SampleNode>
<Widget>Widget1</Widget>
</SampleNode>
<Widget>Widget3</Widget>
</TopNode>
Notes:
<Widget>
nodes can appear in multiple places in the hierarchySpecial
attribute in one of the places it occurs.Here is my (working) existing code for getting the unique values:
<xsl:key name="unique-widgets" match="//Widget" use="text()"/>
<xsl:for-each select="//Widget[count(. | key('unique-widgets', text())[1]) = 1]">
<xsl:sort select="."/>
<div class="widget-col">
<xsl:apply-templates select="current()"/>
</div>
</xsl:for-each>
Here is what I initially tried for checking the attribute only to remember I no longer had actual nodes, but just the text values after doing the Muenchian grouping:
<xsl:key name="unique-widgets" match="//Widget" use="text()"/>
<xsl:for-each select="//Widget[count(. | key('unique-widgets', text())[1]) = 1]">
<xsl:sort select="."/>
<div class="widget-col">
<xsl:if test="current()/@Special">
<xsl:attribute name="class">
widget-col special
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="current()"/>
</div>
</xsl:for-each>
Expected output:
<div class="widget special">Widget1</div>
<div class="widget">Widget2</div>
<div class="widget">Widget3</div>
Is it possible to collect this information as part of the XML grouping? If not, what's the most efficient way to look it up for each value?
Upvotes: 0
Views: 81
Reputation: 116959
Muenchian grouping returns the first node of each group (in document order). If you want to know if any node in the group has a specific attribute, you need to use the key again in order to query the group:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:key name="unique-widgets" match="Widget" use="." />
<xsl:template match="/">
<xsl:for-each select="//Widget[count(. | key('unique-widgets', .)[1]) = 1]">
<xsl:sort select="."/>
<div class="widget-col">
<xsl:if test="key('unique-widgets', .)/@Special">
<xsl:attribute name="class">widget-col special</xsl:attribute>
</xsl:if>
<xsl:value-of select="."/>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1