Holge r: XSLT 2.0 function für Spreadsheetspalten

Hallo,

ich habe da ein leidiges Problem, was ich schon immer mal in Angriff nehmen wollte. Ziel soll es sein, ein xsl:function zu erstellen, die eine Nummer in eine Spreadsheet Letter Code umwandelt, Also ganz einfach 1 = A, 5 = E; 27 = AA usw. Zur Zeit regele ich das über eine Templatekombination, die zwar ihre Aufgabe erfüllt, aber mir nicht so richtig gefällt und eher auf die schnelle geschrieben wurde. Eher mag ich xf:translate-column-number($ColumnNumber) einfach aufrufen, als die Template kombination. Nur weiss ich nicht so recht wie ich da am besten herangehe unter xslt2.0.

Abfrage erfolgt über:

<xsl:call-template name="translateColumnNumberToColumnLetter">
 <xsl:with-param name="currentColumn" select="$ColumnNumber"/>
</xsl:call-template>

<xsl:template name="translateColumnNumberToColumnLetter">
        <xsl:param name="currentColumn" select="0"/>
        <xsl:param name="FirstLetter" select="0"/>

xsl:choose
            <xsl:when test="$FirstLetter &lt; 27">
                xsl:choose
                    <xsl:when test="$currentColumn &lt; 27">
                        <xsl:call-template name="getColumnLetter">
                            <xsl:with-param name="FirstLetter" select="$FirstLetter"/>
                            <xsl:with-param name="SecondLetter" select="$currentColumn"/>
                        </xsl:call-template>
                    </xsl:when>
                    xsl:otherwise
                        <xsl:call-template name="translateColumnNumberToColumnLetter">
                            <xsl:with-param name="FirstLetter" select="$FirstLetter + 1"/>
                            <xsl:with-param name="currentColumn" select="$currentColumn - 26"/>
                        </xsl:call-template>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            xsl:otherwise
                <xsl:value-of select="'only Column to XX supported'"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

<xsl:template name="getColumnLetter">
        <xsl:param name="FirstLetter"/>
        <xsl:param name="SecondLetter"/>
        <xsl:call-template name="ColumnLetter">
            <xsl:with-param name="Number" select="$FirstLetter"/>
        </xsl:call-template>
        <xsl:call-template name="ColumnLetter">
            <xsl:with-param name="Number" select="$SecondLetter"/>
        </xsl:call-template>
    </xsl:template>

<xsl:template name="ColumnLetter">
        <xsl:param name="Number"/>
        <xsl:if test="$Number != 0">
            <xsl:if test="$Number = 1">
                xsl:textA</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 2">
                xsl:textB</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 3">
                xsl:textC</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 4">
                xsl:textD</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 5">
                xsl:textE</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 6">
                xsl:textF</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 7">
                xsl:textG</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 8">
                xsl:textH</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 9">
                xsl:textI</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 10">
                xsl:textJ</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 11">
                xsl:textK</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 12">
                xsl:textL</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 13">
                xsl:textM</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 14">
                xsl:textN</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 15">
                xsl:textO</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 16">
                xsl:textP</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 17">
                xsl:textQ</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 18">
                xsl:textR</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 19">
                xsl:textS</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 20">
                xsl:textT</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 21">
                xsl:textU</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 22">
                xsl:textV</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 23">
                xsl:textW</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 24">
                xsl:textX</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 25">
                xsl:textY</xsl:text>
            </xsl:if>
            <xsl:if test="$Number = 26">
                xsl:textZ</xsl:text>
            </xsl:if>
        </xsl:if>
    </xsl:template>

  1. Hallo Holge r,

    Hallo,

    ich habe da ein leidiges Problem, was ich schon immer mal in Angriff nehmen wollte. Ziel soll es sein, ein xsl:function zu erstellen, die eine Nummer in eine Spreadsheet Letter Code umwandelt, Also ganz einfach 1 = A, 5 = E; 27 = AA usw.

    ...

    Nur weiss ich nicht so recht wie ich da am besten herangehe unter xslt2.0.

    Hier mal ein Versuch:

    <?xml version="1.0" encoding="ISO-8859-1"?>  
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
     xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"  
     xmlns:my="http://example.org/my">  
      
    <!-- globale Variable -->  
    <xsl:variable name="abisz" select="('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')"/>  
      
    <!-- Testaufrufe -->  
    <xsl:template match="/">  
      <xsl:value-of select="my:xyz(5)"/><!-- E -->  
      <xsl:text> | </xsl:text>  
      <xsl:value-of select="my:xyz(27)"/><!-- E -->  
      <xsl:text> | </xsl:text>  
      <xsl:value-of select="my:xyz(54)"/><!-- AAB -->  
    </xsl:template>  
      
    <!-- die eigentliche Funktion -->  
    <xsl:function name="my:xyz">  
      <xsl:param name="z"/>  
      
      <xsl:variable name="x" select="$z div 26"/>  
      <xsl:value-of select="if($x le 1) then $abisz[$z] else $abisz[1]"/>  
      <xsl:value-of select="if($x gt 1) then my:xyz($z - 26) else()"/>  
    </xsl:function>  
      
    </xsl:stylesheet>
    

    Grüße,
    Thomas

    1. <xsl:value-of select="my:xyz(27)"/><!-- E -->

      Nur falsch kopiert, hier kommt AA heraus.

      Grüße,
      Thomas

    2. Perfect! Ich glaube ich muss mich jetzt doch mal in XQuery einarbeiten ;-)

      Vielen Dank! H.

  2. Hallo,

    ich habe da ein leidiges Problem, was ich schon immer mal in Angriff nehmen wollte. Ziel soll es sein, ein xsl:function zu erstellen, die eine Nummer in eine Spreadsheet Letter Code umwandelt, Also ganz einfach 1 = A, 5 = E; 27 = AA usw.

    Hier eine andere Lösung:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:sdml="http://www.selfhtml.org" exclude-result-prefixes="sdml">
     <xsl:variable name="spalten">
      <xsl:for-each select="1 to 78">
       <spalte id="{position()}" />
      </xsl:for-each>
     </xsl:variable>
     <xsl:function name="sdml:createColumLetter">
      <xsl:param name="l" />
      <xsl:param name="c" />
      <xsl:param name="n" />
      <xsl:variable name="letters" select="tokenize('A B C D E F G H I J K L M N O P Q R S T U V W X Y Z', ' ')" />
      <xsl:sequence select="if(($n div 26) &lt;= 1) then concat($l, $letters[position() = $n]) else sdml:createColumLetter(concat($l, $letters[position() = $c]), ($c + 1), ($n - 26))"></xsl:sequence>
     </xsl:function>
     <xsl:template match="/">
      <xsl:for-each select="$spalten/spalte">
       <spalte name="{@id}" id="{sdml:createColumLetter('', 1, @id)}" />
      </xsl:for-each>
     </xsl:template>
    </xsl:stylesheet>

    das XSL an sich angewendet liefert:

    <?xml version="1.0" encoding="UTF-8"?>
    <spalte name="1" id="A"/>
    ...
    <spalte name="5" id="E"/>
    ...
    <spalte name="26" id="Z"/>
    <spalte name="27" id="AA"/>
    ...
    <spalte name="52" id="AZ"/>
    <spalte name="53" id="ABA"/>
    ...
    <spalte name="78" id="ABZ"/>

    Grüße
    Thomas