Erstellungsliste mit xslt

Ich versuche, eine Liste zu erstellen, die mein gesamtes XML-Dokument analysiert. Ich muss die numerischen Namen und dann die Alphanamen auflisten. Die Liste sollte etwa so aussehen.

6
6600 Training
6500 Training

A
Accelerated Training

T
Training

Dies ist ein Ausschnitt der XML.

<courses>
    <course>         
        <name>Accelerated Training</name>
    </course>
    <course>        
        <name>6600 Training</name>
    </course>   
         <course>        
        <name>Training</name>
    </course>
    <course>        
        <name>6500 Training</name>
    </course>   

</courses>   

Dies ist der Code, den ich gerade verwende. Ich fand dies in einer anderen Frage auf der Website und habe es etwas angepasst. Derzeit berücksichtigt es nicht meine Notwendigkeit, nach Zahl zu analysieren und es kehrt auch aus alphabetischer Reihenfolge zurück.

<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="vLower" select= "'abcdefghijklmnopqrstuvwxyz'"/> 
  <xsl:variable name="vUpper" select= "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/> 

  <xsl:key name="kTitleBy1stLetter" match="courses/course"  use="substring(name,1,1)"/>    

  <xsl:template match="/*">      

    <xsl:for-each select="course [generate-id() = generate-id(key('kTitleBy1stLetter', substring(name,1,1)) [1] ) ]">        
      <xsl:variable name="v1st" select="substring(name,1,1)"/>        
      <h2><xsl:value-of select="$v1st"/></h2>        
      <div class="{translate($v1st, $vUpper, $vLower)}-content">
        <ul>
          <xsl:for-each select="key('kTitleBy1stLetter',$v1st)">               
            <li><xsl:value-of select="name"/></li>
          </xsl:for-each>          
        </ul>      
      </div>      
    </xsl:for-each>        
  </xsl:template>
</xsl:stylesheet>

Antwort auf "Erstellungsliste mit xslt " 3 von antworten

Nun, der Zahlenteil ist knifflig, wenn du etwas Komplexes willst, aber basierend auf deiner idealen Ausgabe fehlt nur ein einfaches sort on your for-each: auf deinem für jeden:

<xsl:sort select="key('kTitleBy1stLetter', substring(name,1,1))" />

Vorbehalt: Ich mache keine Behauptungen darüber, dass dies die beste oder einzige oder andere Methode ist, nur dass dies voll stop funktioniert und verwendet, was du bereits hast.

Grundsätzlich müssen Sie nach dem ersten Buchstaben gruppieren und nach <name>. You are on a good way with your Muenchian grouping approach already. sortieren. Sie sind bereits auf einem guten Weg mit Ihrem muenchian Gruppierung Ansatz.

Ich würde eine Alternative vorschlagen, die ein bisschen einfacher auf das Auge ist:

<xsl:key name="kInitial" match="course" use="substring(name, 1, 1)" />

<xsl:template match="courses">
  <xsl:apply-templates select="course" mode="initial">
    <xsl:sort select="name" />
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="course" mode="initial">
  <xsl:variable name="initial" select="substring(name, 1, 1)" />
  <xsl:variable name="courses" select="key('kInitial', $initial)" />
  <xsl:if test="generate-id() = generate-id($courses[1])">
    <h2><xsl:value-of select="$initial"/></h2>
    <ul>
      <xsl:apply-templates select="$courses">
        <xsl:sort select="name" />
      </xsl:apply-templates>
    </ul>
  </xsl:if>
</xsl:template>

<xsl:template match="course">
  <li>
    <xsl:value-of select="name"/>
  </li>
</xsl:template>

Ausgänge:

<h2>6</h2>
<ul>
  <li>6500 Training</li>
  <li>6600 Training</li>
</ul>
<h2>A</h2>
<ul>
  <li>Accelerated Training</li>
</ul>
<h2>T</h2>
<ul>
  <li>Training</li>
</ul>

EDIT: Aus Gründen der Lesbarkeit habe ich das Obergehäuse des ersten Buchstabens weggelassen. Der richtige Schlüssel wäre dieser (Sie können keine Variable in einem Schlüssel verwenden, daher die Literal-Alphabet-Zeichenfolgen):

<xsl:key name="kInitial" match="course" use="
  translate(
    substring(name, 1, 1), 
    'abcdefghijklmnopqrstuvwxyz', 
    'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  )
" />

Das gleiche gilt natürlich für die Variable $initial variable in the second template, but here you can in fact use variables again. in der zweiten Vorlage, aber hier können Sie tatsächlich wieder Variablen verwenden.

EDIT #2: Da beim Sortieren auch die Groß-/Kleinschreibung beachtet wird, können Sie den gleichen Ausdruck verwenden:

<xsl:sort select="translate(substring(name, 1, 1), $vLower, $vUpper)" />

An XSLT 2.0 Lösung :

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="/*">
      <xsl:for-each-group select="course"
           group-by="upper-case(substring(name,1,1))">
        <xsl:sort select="current-grouping-key()"/>

        <xsl:sequence select=
           "concat('&#xA;', current-grouping-key())"/>

        <xsl:for-each select="current-group()">
          <xsl:sort select="upper-case(name)"/>
          <xsl:sequence select="concat('&#xA;&#x9;', name)"/>
        </xsl:for-each>
      </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

Wenn die obige Transformation auf das ursprünglich bereitgestellte XML-Dokument angewendet wird:

<courses>
    <course>
        <name>Accelerated Training</name>
    </course>
    <course>
        <name>6600 Training</name>
    </course>
    <course>
        <name>Training</name>
    </course>
    <course>
        <name>6500 Training</name>
    </course>
</courses>

wird das gewünschte Ergebnis (im Textformat der Einfachheit -- die Erstellung des Html-Codes wird als Übung für den Leser :)

6 
    6500 Training 
    6600 Training 
A 
    Accelerated Training 
T 
    Training

Beachten Sie :

  1. Die Verwendung der <xsl:for-each-group> XSLT 2.0 Anweisung

  2. Die Verwendung der Funktionen current-grouping-key() und current-group() XSLT 2.0.

  3. Die Verwendung der upper-case() XPath 2.0-Funktion