Announcement

Collapse
No announcement yet.

summieren eines strings

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • summieren eines strings

    Hey

    Ich will die einzelnen Teile des Inhaltes des Elements "zahl" summieren

    <zahl>1 2 3 4 5 6</zahl>

    Also 1 + 2 + 3 + 4 + 5 + 6 = 21

    Wie kann ich dies mit XSLT umsetzen. Hab es versucht mit substring after / before und das ganze rekursiv, bin aber leider gescheitert....

    Danke im Vorraus

  • #2
    Wenn XSLT 2.0 + XPath 2.0 nutzbar sind, dann so:

    Code:
    <xsl:template match="zahl">
    
      <xsl:variable name="zahlen" select="fn:tokenize(.,' ')"/>
      <xsl:value-of select="fn:sum(for $i in $zahlen return fn:number($i))"/><!-- 21 -->
    
    </xsl:template>
    Ansonsten mittels rekursivem Template-Aufruf:

    Code:
    <xsl:template match="zahl">
    
      <xsl:call-template name="summe">
        <xsl:with-param name="zahlen" select="."/>
        <xsl:with-param name="i" select="1"/>
        <xsl:with-param name="max" select="string-length(.)"/>
        <xsl:with-param name="summe" select="0"/>
      </xsl:call-template>
    
    </xsl:template>
    
    
    <xsl:template name="summe">
    
      <xsl:param name="i" select="$i"/>
      <xsl:param name="max" select="$max"/>
      <xsl:param name="summe" select="$summe"/>
      <xsl:param name="zahlen" select="$zahlen"/>
    
      <xsl:choose>
        <xsl:when test="$i &lt;= $max">
          <xsl:variable name="zahl" select="number(substring($zahlen,$i,1))"/>
          <xsl:call-template name="summe">
            <xsl:with-param name="i" select="$i + 2"/>
            <xsl:with-param name="max" select="$max"/>
            <xsl:with-param name="summe" select="$summe + $zahl"/>
            <xsl:with-param name="zahlen" select="$zahlen"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$summe"/><!-- 21 -->
        </xsl:otherwise>
      </xsl:choose>
    
    </xsl:template>
    Hinweis: Beide Code-Fragmente gehen von exakt einem Leerzeichen zwischen den einzelnen Ziffern aus!

    Comment


    • #3
      Nachtrag: Bei der rekursiven Lösung ist ggf. noch etwas Feintuning nötig, wenn es sich nicht nur um einstellige Zahlenwerte handelt.

      Comment


      • #4
        Hier noch eine robustere Alternative mit substring-before bzw. -after:

        Code:
        <xsl:template match="zahl">
        
          <xsl:call-template name="summe">
            <xsl:with-param name="zahlen" select="."/>
            <xsl:with-param name="summe" select="0"/>
          </xsl:call-template>
        
        </xsl:template>
        
        
        <xsl:template name="summe">
        
          <xsl:param name="zahlen" select="$zahlen"/>
          <xsl:param name="summe" select="$summe"/>
        
          <xsl:choose>
        
            <xsl:when test="string-length($zahlen) &gt; 1">
              <xsl:variable name="zahl" select="number(substring-before($zahlen,' '))"/>
              <xsl:call-template name="summe">
                <xsl:with-param name="summe" select="$summe + $zahl"/>
                <xsl:with-param name="zahlen" select="substring-after($zahlen,' ')"/>
              </xsl:call-template>
            </xsl:when>
        
            <xsl:when test="string-length($zahlen) = 1">
              <xsl:variable name="zahl" select="number($zahlen)"/>
              <xsl:call-template name="summe">
                <xsl:with-param name="summe" select="$summe + $zahl"/>
                <xsl:with-param name="zahlen" select="''"/>
              </xsl:call-template>
            </xsl:when>
        
            <xsl:otherwise>
              <xsl:value-of select="$summe"/><!-- 21 -->
            </xsl:otherwise>
        
          </xsl:choose>
        
        </xsl:template>

        Comment


        • #5
          Danke für die Antworten. Die Rekursive Lösung arbeitet einwandfrei und werde mir jetz auch nochmal die substring-before / after version anschauen.

          Comment


          • #6
            Das mit der string-lentgh ist grenzwertig.

            Ich habe das gerade (durch Euch inspiriert) sinngemaess so geloest (mit | als Trennzeichen):
            Code:
            <xsl:variable name="summanden">12|13|1|4|6</xsl:variable>
            
            <xsl:variable name="summe">
                      <xsl:call-template name="summiere">
                        <xsl:with-param name="zahlen" select="$summanden"/>
                        <xsl:with-param name="summe" select="0"/>
                      </xsl:call-template>
             </xsl:variable>
            
            <xsl:template name="summiere">
                      <xsl:param name="zahlen" />
                      <xsl:param name="summe" />
                      <xsl:choose>
                        <xsl:when test="contains($zahlen,'|')"><!-- we have (still) more than one number -->
                          <xsl:variable name="zahl" select="substring-after($zahlen,'|')"/>
                          <xsl:call-template name="summiere">
                            <xsl:with-param name="summe" select="$summe + number(substring-before($zahlen,'|'))"/>
                            <xsl:with-param name="zahlen" select="$zahl"/>
                          </xsl:call-template>
                        </xsl:when>
                        <xsl:otherwise><!-- we are through -->
                          <xsl:value-of select="$summe + number($zahlen)"/>
                        </xsl:otherwise>
                      </xsl:choose>        
                </xsl:template>

            Comment

            Working...
            X