c32hedge
c32hedge

Reputation: 820

Get unique set of nodes by value, then see if any nodes for a value have attribute in XSLT 1.0

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:

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

Answers (2)

Martin Honnen
Martin Honnen

Reputation: 167426

Make the check test="key('unique-widgets', .)/@Special".

Upvotes: 0

michael.hor257k
michael.hor257k

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

Related Questions