Re: [xsl] Question about grouping attributes using keys

Subject: Re: [xsl] Question about grouping attributes using keys
From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx>
Date: Thu, 19 Apr 2007 22:03:02 +0530
I can suggest something like below (tested with IE 6.0):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                      version="1.0">

<xsl:output method="html" />

  <xsl:key name="UNIQUE_ATTRS" match="ITEM" use="@ATTR" />
  <xsl:key name="UNIQUE_ELEMS" match="ITEM" use="ELEM" />

  <xsl:template match="/">
    <xsl:call-template name="test">
      <xsl:with-param name="theKey" select="'UNIQUE_ELEMS'"/>
      <xsl:with-param name="theName" select="'ELEM'"/>
    </xsl:call-template>
    <xsl:call-template name="test">
      <xsl:with-param name="theKey" select="'UNIQUE_ATTRS'"/>
      <xsl:with-param name="theName" select="'ATTR'"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="test">
    <xsl:param name="theKey" select="." />
    <xsl:param name="theName" select="." />
    <p>
      <xsl:value-of select="concat('key: ', $theKey)" /><br/>
      <xsl:value-of select="concat('node: ', $theName)"/><br/>
      <xsl:text>values:</xsl:text>
      <xsl:variable name="rtf">
        <xsl:for-each select="ROOT/ITEM[generate-id() =
generate-id(key($theKey, ELEM)[1])]">
          <xsl:value-of select="." />
        </xsl:for-each>
        <xsl:for-each select="ROOT/ITEM[generate-id() =
generate-id(key($theKey, @ATTR)[1])]">
	   <xsl:value-of select="@ATTR" /><xsl:text> </xsl:text>
        </xsl:for-each>
      </xsl:variable>
      <xsl:value-of select="msxsl:node-set($rtf)" />
    </p>
  </xsl:template>

</xsl:stylesheet>

It seems, it's difficult to make the stylesheet more generic than this.

On 4/19/07, Waters, Tyler S FOR:EX <Tyler.Waters@xxxxxxxxx> wrote:
I'm trying to write a generic function to output a list of unique values
on a selected node, whether it be an Element or Attribute.  I've got the
Element portion working fine, but Attributes don't seem to want to run
through the for-each loop....  Here's a test which highlights this:

test.xml:

       <?xml version="1.0" encoding="ISO8859-1" ?>
       <?xml-stylesheet type="text/xsl" href="test.xsl"?>
       <ROOT>
               <ITEM ATTR="A1">
                       <ELEM>E1</ELEM>
               </ITEM>
               <ITEM ATTR="A1">
                       <ELEM>E1</ELEM>
               </ITEM>
               <ITEM ATTR="A2">
                       <ELEM>E2</ELEM>
               </ITEM>
               <ITEM ATTR="A2">
                       <ELEM>E2</ELEM>
               </ITEM>
               <ITEM ATTR="A3">
                       <ELEM>E3</ELEM>
               </ITEM>
               <ITEM ATTR="A3">
                       <ELEM>E3</ELEM>
               </ITEM>
       </ROOT>

test.xsl:

       <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">
       <xsl:output method="html" />
       <xsl:key name="UNIQUE_ATTRS" match="ITEM" use="@ATTR" />
       <xsl:key name="UNIQUE_ELEMS" match="ITEM" use="ELEM" />

       <xsl:template match="/">
               <xsl:call-template name="test">
                       <xsl:with-param name="theKey"
select="'UNIQUE_ELEMS'"/>
                       <xsl:with-param name="theName" select="'ELEM'"/>
               </xsl:call-template>
               <xsl:call-template name="test">
                       <xsl:with-param name="theKey"
select="'UNIQUE_ATTRS'"/>
                       <xsl:with-param name="theName" select="'ATTR'"/>
               </xsl:call-template>
       </xsl:template>

       <xsl:template name="test">
               <xsl:param name="theKey" select="." />
               <xsl:param name="theName" select="." />
               <p>
               <xsl:value-of select="concat('key: ', $theKey)" /><br/>
               <xsl:value-of select="concat('node: ', $theName)"
/><br/>
               <xsl:text>values:</xsl:text>
               <xsl:for-each select="ROOT/ITEM[ generate-id() =
generate-id( key( $theKey, *[local-name()=$theName] ) [1] ) ]">
                       <xsl:value-of select="." />
               </xsl:for-each>
               </p>
       </xsl:template>
       </xsl:stylesheet>

Opening "test.xml" returns:

       key: UNIQUE_ELEMS
       node: ELEM
       values: E1 E2 E3

       key: UNIQUE_ATTRS
       node: ATTR
       values:

Why is it that "A1 A2 A3" is not returned for the ATTR node?  Is there
any way to write a generic for-each select expression that takes the
node name & key name and works for both elements and attributes?   Any
help is greatly appreciated

Thanks,
-Tyler Waters

-- Regards, Mukul Gandhi

Current Thread