Announcement

Collapse
No announcement yet.

Liste alphabetisch gruppieren

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

  • Liste alphabetisch gruppieren

    Ich habe eine Liste. Z.B.
    • Ameli
    • Berta
    • Bingo
    • Bolze
    • Constanze
    • ...


    Nun möchte ich die Anzeige etwas aufwerten:

    A
    • Ameli

    B
    • Berta
    • Bingo
    • Bolze

    C
    • Constanze


    Ich glaube das Anliegen ist klar. Ich weiß, dass man mit XML den ersten Buchstaben des aktuellen Namens ermitteln könnte. Aber wie kann man eine Ausgabe innerhalb eines for-each immer dann machen, wenn der erste Buchstabe sich ändert?

  • #2
    Nutze die substring()-Funktion innerhalb der Gruppierung, siehe auch Grouping by first letter.

    Comment


    • #3
      Grouping by first letter scheint ja ne gute Geschichte zu sein. ich bekomm sie nur nicht zum laufen.

      Habe mal exakt das Beispiel nachgebaut:

      text.xml:
      Code:
      <?xml version="1.0"?>
      <?xml-stylesheet type="text/xsl" href="test.xsl"?>
      <counties>
        <county>Anderson</county>
        <county>Bailey</county>
        <county>Bailey</county>
        <county>Bailey</county>
        <county>Columbus</county>
        <county>Carneval</county>
        <county>Daisey</county>
        <county>Donald</county>
        <county>Hallo</county>
        <county>Welt</county>
        <county>Zug</county>
      </counties>
      test.xsl:
      Code:
      <?xml version="1.0" encoding="ISO-8859-1"?>
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="html"/>
      
        <xsl:key name="county-initial" match="county" use="substring(.,1,1)"/>
        
        <xsl:template match="counties">
          <table>
            <xsl:call-template name="accumulate">
              <xsl:with-param name="countylist" select="county"/>
              <xsl:with-param name="startlist" select="/.."/>
              <xsl:with-param name="maxcount" select="0"/>
            </xsl:call-template>
          </table>
        </xsl:template>
      
        <xsl:template name="accumulate">
          <xsl:param name="countylist"/>
          <xsl:param name="startlist"/>
          <xsl:param name="maxcount"/>
          <xsl:choose>
            <xsl:when test="$countylist">
              <xsl:variable name="initial" select="substring($countylist[1],1,1)"/>
              <xsl:variable name="currentcount" select="count(key('county-initial',$initial))"/>
              <xsl:choose>
                <xsl:when test="$currentcount &gt; $maxcount">
                  <xsl:call-template name="accumulate">
                    <xsl:with-param name="countylist" select="$countylist[not(substring(.,1,1)=$initial)]"/>
                    <xsl:with-param name="startlist" select="$startlist|$countylist[1]"/>
                    <xsl:with-param name="maxcount" select="$currentcount"/>
                  </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:call-template name="accumulate">
                    <xsl:with-param name="countylist" select="$countylist[not(substring(.,1,1)=$initial)]"/>
                    <xsl:with-param name="startlist" select="$startlist|$countylist[1]"/>
                    <xsl:with-param name="maxcount" select="$maxcount"/>
                  </xsl:call-template>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
              <!-- use Wendell Pietz' method for iterating over 1..$maxcount -->
              <xsl:for-each select="(//node())[position() &lt;= $maxcount]">
                <xsl:variable name="index" select="position()"/>
                <ul>
                  <xsl:for-each select="$startlist">
                    <xsl:for-each select="key('county-initial',substring(.,1,1))[$index]">
                      <li><xsl:value-of select="."/></li>
                    </xsl:for-each>
                  </xsl:for-each>
                </ul>
              </xsl:for-each>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:template>
      
      </xsl:stylesheet>
      Damit erhalte ich folgende Ausgabe:
      • Anderson
      • Bailey
      • Columbus
      • Daisey
      • Hallo
      • Welt
      • Zug

      • Bailey
      • Carneval
      • Donald

      • Bailey


      Das verstehe ich nicht so richtig? Was macht der da? Wieso drei Listen? Was ist die Startliste? Kann jemand noch was dazu sagen?

      Comment


      • #4
        Es werden zwei verschachtelte Gruppierungen benötigt. Hier ein alternativer Ansatz, der zur gewünschten Ausgabe führen sollte:
        Code:
        <?xml version="1.0" encoding="UTF-8"?>
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        
          <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"  
            doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
            doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
        
          <xsl:key name="groupbycounty" match="county" use="."/>
          <xsl:key name="groupbycounty1stletter" match="county" use="substring(.,1,1)"/>
        
          <xsl:template match="/">
            <html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
            <head><title>Test</title></head><body> 
        
            <xsl:for-each select="/counties/county[generate-id() =
              generate-id(key('groupbycounty1stletter',substring(.,1,1))[1])]">
        
              <xsl:sort select="substring(.,1,1)" order="ascending" data-type="text"/>
              <xsl:variable name="letter" select="substring(.,1,1)"/>
        
              <xsl:for-each select="/counties/county[generate-id() =
                generate-id(key('groupbycounty',.)[1])]">
        
                <xsl:if test="position() = 1">
                  <h1><xsl:value-of select="$letter"/></h1>
                  <xsl:text disable-output-escaping="yes">&lt;ul&gt;</xsl:text>
                </xsl:if>
        
                <xsl:if test="substring(.,1,1) = $letter">
                  <li><xsl:value-of select="."/></li>
                </xsl:if>
        
                <xsl:if test="position() = last()">
                  <xsl:text disable-output-escaping="yes">&lt;/ul&gt;</xsl:text>
                </xsl:if>
        
              </xsl:for-each>
        
            </xsl:for-each>
        
            </body></html>
          </xsl:template>
        
        </xsl:stylesheet>

        Comment

        Working...
        X