views:

884

answers:

1

Hi

I have the following xsl template that I'm using to group my xsl. The problem I have is that I need to uppercase the @Title as currently my grouping is seeing upper and lowercase as seperate groups.

  <xsl:key name="rows-by-title" match="Row" use="substring(@Title,1,1)" />

    <xsl:template name="Meunchian" match="/dsQueryResponse/Rows">


      <xsl:for-each select="Row[count(. | key('rows-by-title', substring(@Title,1,1))[1]) = 1]">


       <xsl:sort select="substring(@Title,1,1)" />

       <p></p><xsl:value-of select="substring(@Title,1,1)" /><br />
        <xsl:for-each select="key('rows-by-title', substring(@Title,1,1))">
         <xsl:value-of select="@Title" /><br/>
        </xsl:for-each>

      </xsl:for-each>

    </xsl:template>

I tried to use call-template and set a variable but xsl does not seem to like this:

 <xsl:key name="rows-by-title" match="Row" use="substring(@Title,1,1)" />

    <xsl:template name="Meunchian" match="/dsQueryResponse/Rows">



      <xsl:for-each select="Row[count(. | key('rows-by-title', substring(@Title,1,1))[1]) = 1]">

    <xsl:variable name="myTitle">

          <xsl:call-template name="to-upper">
            <xsl:with-param name="text">
             <xsl:value-of select="@Title"/>
            </xsl:with-param>
          </xsl:call-template>

    </xsl:variable>

       <p></p><xsl:value-of select="$myTitle" /><br />
        <xsl:for-each select="key('rows-by-title', substring(@Title,1,1))">
         <xsl:value-of select="@Title" /><br/>
        </xsl:for-each>

      </xsl:for-each>

    </xsl:template>

What I am trying to achieve is meunchian grouping but without case sensitivity - hope this makes Sense!

Kieran

+2  A: 

The way to convert lower-case letters to upper is to use the XPath translate() function.

Using it, one way to express the desired transformation is the following:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output method="xml"/>

 <xsl:variable name="vLower" select=
  "'abcdefghijklmnopqrstuvwxyz'"
  />

 <xsl:variable name="vUpper" select=
  "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"
  />

 <xsl:key name="rows-by-title" match="Row" use=
 "translate(substring(@Title,1,1),
            'abcdefghijklmnopqrstuvwxyz',
            'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
            )" />

    <xsl:template match="/">
     <html>
      <xsl:apply-templates select="*/*"/>
     </html>
    </xsl:template>

    <xsl:template name="Meunchian" match="/dsQueryResponse/Rows">
     <xsl:for-each select=
       "Row[generate-id()
           =
            generate-id(key('rows-by-title',
                             translate(substring(@Title,1,1),
                                       $vLower,
                                       $vUpper)
                             )[1]
                       )
            ]">
      <xsl:sort select="translate(substring(@Title,1,1),
                                           $vLower,
                                           $vUpper)" />
      <p></p>
      <xsl:value-of select="translate(substring(@Title,1,1),
                                               $vLower,
                                               $vUpper)" />
      <br />
      <xsl:for-each select=
                             "key('rows-by-title', 
                                   translate(substring(@Title,1,1),
                                  $vLower,
                                  $vUpper)">

       <xsl:value-of select="@Title" />
       <br/>
      </xsl:for-each>
     </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

When applied on the following XML document:

<dsQueryResponse>
    <Rows>
     <Row Title="Agenda" />
     <Row Title="Policy" />
     <Row Title="policy" />
     <Row Title="Report" />
     <Row Title="report" />
     <Row Title="Test2" />
     <Row Title="test1" />
     <Row Title="Boo" />
     <Row Title="foo" />
    </Rows>
</dsQueryResponse>

it produces the desired result:

<html>
    <p/>A
    <br/>Agenda
    <br/>
    <p/>B
    <br/>Boo
    <br/>
    <p/>F
    <br/>foo
    <br/>
    <p/>P
    <br/>Policy
    <br/>policy
    <br/>
    <p/>R
    <br/>Report
    <br/>report
    <br/>
    <p/>T
    <br/>Test2
    <br/>test1
    <br/>
</html>

In XPath 2.0 one will use the upper-case() function to convert lower case to upper case.

Also, grouping in XSLT 2.0 can be better expressed using the <xsl:for-each-group> instruction.

Dimitre Novatchev