Alex Schneider: ebene Struktur in Baumstruktur

Hallo,

ich weiß, ich habe schon so einen Artikel gesehen -ich finde ihn nur nicht.

Es handelt sich um diese Struktur:
<verzeichnis>
 <object level="1"/>
 <object level="2"/>
 <object level="3"/>
 <object level="1"/>
 <object level="2"/>
 <object level="2"/>
 <object level="1"/>
 <object level="2"/>
 <object level="3"/>
 <object level="2"/>
</verzeichnis>

Als Baum sollte das dann so Aussehen:

<verzeichnis>
 <object level="1">
   <object level="2">
      <object level="3"/>
        </objekt>
      </objekt>
 <object level="1">
   <object level="2"/>
   <object level="2"/>
      <objekt>
 <object level="1">
    <object level="2">
       <object level="3"/>
         </objekt>
    <object level="2"/>
       <object>
</verzeichnis>

Die Objekte haben selbstverständlich weitere Kindelemente und die Objekttiefe sollte nicht beschränkt sein.

Ich bin bis hierhin gelangt:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <verzeichnis>
   <xsl:apply-templates select="verzeichnis/object[attribute::level=1]"/>
  </verzeichnis>
 </xsl:template>

<xsl:template match="verzeichnis/object">
 <object>
    <xsl:attribute name="level">
     <xsl:value-of select="./@level"/>
    </xsl:attribute>

<xsl:variable name="descendant">
     <xsl:value-of select="./@level + 1"/>
    </xsl:variable>

<xsl:if test="$descendant = following-sibling::object[1]/@level">
   <xsl:apply-templates select="following-sibling::object[attribute::level=$descendant]"/>
   <xsl:for-each select="following-sibling::object[attribute::level=$descendant]">
           <xsl:apply-templates select="following-sibling::object[attribute::level=$descendant]"/>
          </xsl:for-each>
      </xsl:if>
    </object>
 </xsl:template>
</xsl:stylesheet>

Gruß Alex

  1. Ich habe es nun doch selber lösen können.
    Hier das XSLT-Skript:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
     <xsl:template match="/">
      <VERZEICHNIS>
       <xsl:apply-templates select="//object[attribute::level=1]" mode="NEXT">
       <!-- This selects ALL elements <object level="1"> -->
        <xsl:with-param name="LIMES" select="number(1)"/>
        <!-- start-value of the parameter $LIMES is 1 -->
       </xsl:apply-templates>
      </VERZEICHNIS>
     </xsl:template>

    <xsl:template match="object" mode="NEXT">
     <xsl:param name="LIMES"/>
      <xsl:if test="@level = $LIMES">
      <!-- These are the searched elements -->
       <xsl:element name="DING">
         <xsl:attribute name="EBENE">
          <xsl:value-of select="./@level"/>
         </xsl:attribute>
         <xsl:if test="$LIMES + 1 = following-sibling::object[1]/@level">
         <!-- Is the next object-element one level higher? -->
          <xsl:apply-templates select="following-sibling::object[1]" mode="NEXT">
          <!-- recursion, search on -->
           <xsl:with-param name="LIMES" select="$LIMES + 1"/>
           <!-- In XSL, the variables are only valid inside their frame, C++ like! -->
          </xsl:apply-templates>
         </xsl:if>
       </xsl:element>

    </xsl:if>
       <xsl:if test="$LIMES <= following-sibling::object[1]/@level">
       <!-- Is the next object-element on the same level? -->
        <xsl:apply-templates select="following-sibling::object[1]" mode="NEXT">
        <!-- recursion, search on -->
         <xsl:with-param name="LIMES" select="$LIMES"/>
        </xsl:apply-templates>
       </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

    1. Nur noch eine kleine Korrektur.
      Am Anfang muss es so aussehen. Es muss "object[1]" stehen. Im vorherigen Skript wählt er alle aus.

      <xsl:template match="/">
        <VERZEICHNIS>
         <xsl:apply-templates select="//object[1][attribute::level=1]" mode="NEXT">
          <xsl:with-param name="LIMES" select="number(1)"/>
          <!-- start-value of the parameter $LIMES is 1 -->
         </xsl:apply-templates>
        </VERZEICHNIS>
       </xsl:template>