spyro: Liste nachträglich hierarchisieren

Hallo zusammen,

ich versuche seit einem Tag verzweifelt ein an sich simples (?) Problem zu lösen. Eine "flache" Liste soll nachträglich hierarchisiert werden. Die Ebene ergibt sich indirekt aus dem Namen (hier: Stufe 1-3) (muss aber nicht unbedingt generisch ermittelt werden). Ich habe das Problem jetzt mal so weit wie möglich heruntergebrochen:

Quell-XML:

  
<root>  
 <p>ABC</p>  
  
 <li_1>1</li_1>  
 <li_2>1.1</li_2>  
 <li_2>1.2</li_2>  
 <li_1>2</li_1>  
 <li_2>2.1</li_2>  
 <li_3>2.1.2</li_3>  
 <li_1>3</li_1>  
 <li_2>3.1</li_2>  
 <li_1>4</li_1>  
 <li_1>5</li_1>  
  
 <p>DEF</p>  
</root>  

Ziel-XML:

  
<root>  
 <abs>ABC</abs>  
  
 <ul>  
  <li>1  
   <ul>  
    <li>1.1</li>  
    <li>1.2</li>  
   </ul>  
  </li>  
  <li>2  
   <ul>  
    <li>2.1  
    <ul>  
     <li>2.1.2</li>  
    </ul>  
  </li>  
  <li>3  
   <ul>  
    <li>3.1</li>  
   </ul>  
  </li>  
  <li>4</li>  
  <li>5</li>  
 </ul>  
  
  
 <abs>DEF</abs>  
</root>  

Ich habe jetzt mit xsl:for-each-group experimentiert und die "Muench'sche Methode" (xsl:generate-id und xsl:key) ausprobiert aber ich stelle mich einfach zu blöd an. Wenn mir hier jemand helfen könnte wäre ich wirklich dankbar.

Viele Grüße,
Spyro

  1. Hallo spyro,

    ich versuche seit einem Tag verzweifelt ein an sich simples (?) Problem zu lösen. Eine "flache" Liste soll nachträglich hierarchisiert werden. Die Ebene ergibt sich indirekt aus dem Namen (hier: Stufe 1-3) (muss aber nicht unbedingt generisch ermittelt werden).

    Naja, eine flache Struktur aufzuwerten ist durchaus eine gewisse Herausforderung. Hier ein Ansatz für das Gruppierungsproblem mit XSLT 2.0-Techniken:

    <xsl:template match="root">  
      <root>  
        <ul>  
          <xsl:for-each-group select="*[fn:contains(fn:local-name(),'li')]" group-starting-with="li_1">  
            <xsl:apply-templates select="."/>  
          </xsl:for-each-group>  
        </ul>  
      </root>  
    </xsl:template>  
      
    <xsl:template match="*[fn:contains(fn:local-name(),'li')]">  
      <xsl:variable name="akt_li" select="fn:local-name()"/>  
      <xsl:variable name="nxt_li" select="fn:concat('li_',fn:number(fn:substring-after($akt_li,'_')) + 1)"/>  
      <li>  
        <xsl:value-of select="."/>  
        <xsl:if test="following-sibling::*[fn:local-name() = $nxt_li][1][preceding-sibling::*[fn:local-name() = $akt_li][1] = current-group()]">  
          <ul>  
            <xsl:for-each-group select="current-group() except ." group-starting-with="*[fn:local-name() = $nxt_li]">  
              <xsl:apply-templates select="."/>  
            </xsl:for-each-group>  
          </ul>  
        </xsl:if>  
      </li>  
    </xsl:template>
    

    Ergebnis:

    <root>  
      <ul>  
        <li>1<ul>  
            <li>1.1</li>  
            <li>1.2</li>  
          </ul>  
        </li>  
        <li>2<ul>  
            <li>2.1<ul>  
                <li>2.1.2</li>  
              </ul>  
            </li>  
          </ul>  
        </li>  
        <li>3<ul>  
            <li>3.1</li>  
          </ul>  
        </li>  
        <li>4</li>  
        <li>5</li>  
      </ul>  
    </root>
    

    Den Rest bekommst Du wohl auch noch hin.

    Grüße,
    Thomas

    1. Hallo Thomas!

      Vielen Dank, das hilft mir wirklich gewaltig weiter. :)
      (Gott, ich liebe dieses Forum!)

      Grüße,
      spyro