2

I'd like to write the alphabet with a link for each letter. So I used templates but I don't how to make this letter I tried that but I had a normal mistake : (A decimal representation must imediately follow the &# in a character reference).

<xsl:template name="alphabet">
    <xsl:param name="iLetter"/>
    <xsl:if test="$iLetter &lt; 91">
        <a><xsl:attribute name="href">req.html?X_letter=&#<xsl:value-of select="$iLetter"/>;</xsl:attribute>&#<xsl:value-of select="$iLetter"/>;</xsl:attribute></a>
        <xsl:call-template name="alphabet">
            <xsl:with-param name="iLetter" select="number($iLetter)+1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

And I call this template ilke that:

<xsl:call-template name="alphabet">
        <xsl:with-param name="iLetter" select="number(65)"/>
</xsl:call-template>

So, I'd like to obtain this result:

A B C D ..... X Y Z without ... of course :)

Adam Wenger
  • 17,100
  • 6
  • 52
  • 63
M07
  • 1,060
  • 1
  • 14
  • 23

4 Answers4

2

The currently accepted answer is incorrect, because it doesn't produce correctly the text child of any a element.

Here is a correct XSLT 1.0 solution:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="/">
     <xsl:call-template name="alphabet"/>
 </xsl:template>

 <xsl:template name="alphabet">
  <xsl:param name="pCode" select="65"/>
  <xsl:if test="not($pCode > 90)">
    <xsl:variable name="vChar" select=
     "substring($vAlpha, $pCode - 64, 1)"/>
    <a href="req.html?X_letter={$vChar}">
     <xsl:value-of select="$vChar"/>
    </a>
    <xsl:call-template name="alphabet">
      <xsl:with-param name="pCode" select="$pCode+1"/>
    </xsl:call-template>
   </xsl:if>
 </xsl:template>
</xsl:stylesheet>

when applied on any XML document (not used), the wanted, correct result is produced:

<a href="req.html?X_letter=A">A</a>
<a href="req.html?X_letter=B">B</a>
<a href="req.html?X_letter=C">C</a>
<a href="req.html?X_letter=D">D</a>
<a href="req.html?X_letter=E">E</a>
<a href="req.html?X_letter=F">F</a>
<a href="req.html?X_letter=G">G</a>
<a href="req.html?X_letter=H">H</a>
<a href="req.html?X_letter=I">I</a>
<a href="req.html?X_letter=J">J</a>
<a href="req.html?X_letter=K">K</a>
<a href="req.html?X_letter=L">L</a>
<a href="req.html?X_letter=M">M</a>
<a href="req.html?X_letter=N">N</a>
<a href="req.html?X_letter=O">O</a>
<a href="req.html?X_letter=P">P</a>
<a href="req.html?X_letter=Q">Q</a>
<a href="req.html?X_letter=R">R</a>
<a href="req.html?X_letter=S">S</a>
<a href="req.html?X_letter=T">T</a>
<a href="req.html?X_letter=U">U</a>
<a href="req.html?X_letter=V">V</a>
<a href="req.html?X_letter=W">W</a>
<a href="req.html?X_letter=X">X</a>
<a href="req.html?X_letter=Y">Y</a>
<a href="req.html?X_letter=Z">Z</a>

II. XSLT 2.0 solution:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:my="my:my" exclude-result-prefixes="xs my"
    xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output omit-xml-declaration="yes" method="xhtml" indent="yes"/>

    <xsl:param name="pStart" as="xs:integer" select="65"/>
    <xsl:param name="pEnd" as="xs:integer" select="90"/>

    <xsl:variable name="vCodes" as="xs:integer*" select=
     "for $i in $pStart to $pEnd
       return $i
     "/>

 <xsl:template match="/">
   <html>
       <xsl:sequence select="my:alphabet()"/>
   </html>
 </xsl:template>

 <xsl:function name="my:alphabet" as="element()*">
  <xsl:for-each select="$vCodes">
    <xsl:variable name="vChar" select="codepoints-to-string(.)"/>
    <a href="req.html?X_letter={$vChar}">
     <xsl:sequence select="$vChar"/>
    </a>
  </xsl:for-each>
 </xsl:function>
</xsl:stylesheet>
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
0

Inside of the a element content you could disable output escaping as in

<a href="req.html?X_letter={$iLetter}">
  <xsl:value-of select="concat('&amp;#', $iLetter, ';')" disable-output-escaping="yes"/>
</a>

That approach does not work within attribute nodes however so I left that part to pass the character code, not the character.

Also be warned that disable-output-escaping is an optional serialization feature that is not supported with all XSLT processors, for instance Firefox/Mozilla's built-in XSLT processor does not serialize the result tree but simply renders it so there the approach is not going to work.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
0

As Martin suggests it would be better to avoid using disable-output-escaping. You don't need it either, if you are would be satisfied with a plain ascii character instead of the numerical character reference. If so, you can use substring and a alphabet lookup-string like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="alphabet" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

    <xsl:template name="alphabet"> 
        <xsl:param name="iLetter" select="65"/> 
        <xsl:if test="$iLetter &lt; 91"> 
            <a>
                <xsl:attribute name="href">req.html?X_letter=<xsl:value-of select="substring($alphabet, $iLetter - 64, 1)"/></xsl:attribute>
                <xsl:value-of select="substring($alphabet, $iLetter - 64, 1)"/>
            </a> 
            <xsl:call-template name="alphabet"> 
                <xsl:with-param name="iLetter" select="number($iLetter)+1"/> 
            </xsl:call-template> 
        </xsl:if> 
    </xsl:template> 

    <xsl:template match="/">
        <xsl:call-template name="alphabet"/> 
    </xsl:template>
</xsl:stylesheet> 

Cheers!

grtjn
  • 20,254
  • 1
  • 24
  • 35
  • It is a very good idea! Thank you Martin Honnen and grtjn for your help. ;) – M07 Nov 26 '11 at 14:21
  • you just wrote a little mistake: and we must write that : There are no link without this substract – M07 Nov 26 '11 at 14:35
0

XSLT 2.0 has the function codepoints-to-string(). With many XSLT 1.0 processors it should be easy enough to implement the same function as an extension function, though it will make your code dependent on that processor.

Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
Michael Kay
  • 156,231
  • 11
  • 92
  • 164