Leeloo5E: MySQL-Baum nach XML-Baum

Hallo,

nachdem ich es geschafft habe, meine Baumstruktur über Nested Sets erfolgreich in meiner MySQL-DB abzuspeichern und auch abzufragen, zu verändern etc., stehe ich jetzt vor dem Problem diese Nested-Sets-Baumstruktur mit Hilfe von PHP in eine XML-Struktur umzuwandeln. Dazu verwende ich die DOM-Funktionen von PHP anstatt einen simplen String zu nehmen und den immer weiter zu vergrößern.

Ok, meine Nested-Sets-Abfrage gibt mir ein Array aller Einträge schon richtig sortiert aus. Dieses Array enthält auch für jeden Eintrag den Level. Level 1 ist hier das Wurzelelement, welches nicht angezeigt werden soll. Also starten wir bei Level 2:

  
 foreach ($nodes as $key=>$item) {  
   if ($item['level'] == 2) {  
    ...  
   }  
 }  

Level 2 ist dann auch gleich ein Elternelement, so dass das erste Kapitel erstellt werden kann. Am Ende soll das dann so aussehen:

  
 <section>  
  <title>Kapitel 1</title>  
  <para>TEXT</para>  
  <section>  
   <title>Kapitel 1.1.</title>  
   <para>TEXT</para>  
  </section>  
  <section>  
   <title>Kapitel 1.2.</title>  
   <para>TEXT</para>  
   <section>  
    <title>Kapitel 1.2.1.</title>  
    <para>TEXT</para>  
   </section>  
  </section>  
 </section>  
 <section>  
  <title>Kapitel 2</title>  
   ....  
 </section>  

Mein Array mit den Einträgen sind dann so aus:

  
 Array (  
  [0] => Array (  
                 [level] => 1  
                 [name] => Wurzel  
  )  
  [1] => Array (  
                 [level] => 2  
                 [name] => Kapitel 1  
  )  
  [2] => Array (  
                 [level] => 3  
                 [name] => Kapitel 1.1  
  )  
  [3] => Array (  
                 [level] => 3  
                 [name] => Kapitel 1.2  
  )  
  [4] => Array (  
                 [level] => 4  
                 [name] => Kapitel 1.1.1  
  )  
  [5] => Array (  
                 [level] => 2  
                 [name] => Kapitel 2  
  )  
 )  

Dummerweise steht bei mir grad einer aufm Schlauch. D.h. die große Erleuchtung hat noch nicht stattgefunden. Meine bisherigen Überlegungen führten jedenfalls immer in eine Sackgasse bzw. zu einem Punkt an dem es nicht weiter geht - für mich zumindest.

Vielleicht hilft es ja schon, dass ich mir das hier von der Seele schreibe, eine Lösung zu finden. Vielleicht hat aber einer von Euch auch noch einen Tipp für mich. THX.

Gruß,
Leeloo

--
"Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
  1. echo $begrüßung;

    Ok, meine Nested-Sets-Abfrage gibt mir ein Array aller Einträge schon richtig sortiert aus. Dieses Array enthält auch für jeden Eintrag den Level.

    Da das gleiche Level in verschiedenen Zweigen auftreten kann, nützt dir diese Information recht wenig. Du benötigst schon noch die Verwandschaftsbeziehungen, zumindest den Verweis auf das Parent-Element. Und anhand dessen solltest du dann die richtige Zuordnung treffen können. Notfalls müsstest du im DOM-Baum die Parent-Information mit hinterlegen, damit du da das Element wiederfindest.

    echo "$verabschiedung $name";

    1. Yo!

      Da das gleiche Level in verschiedenen Zweigen auftreten kann, nützt dir diese Information recht wenig.

      Wenn die Reihenfolge stimmt (d.h. Kindelemente folgen dem Elternelement), reicht das schon.

      Ruben

      PS.: grade im anderen Post war ein Fehler, ich schrieb 2mal = statt ==

      1. Hallo,

        ok, ein Stückchen weiter bin ich schon.

          
         $last = array("level"=>1);  
          
         foreach($nodes AS $key=>$item) {  
          
          # Oberkapitel  
          if ($item['level'] == 2) {  
          
           $section = $dom->createElement('section');  
           $article->appendChild($section);  
           $sectitle = $dom->createElement('title', htmlentities($item['name']));  
           $section->appendChild($sectitle);  
          
          }elseif ($item['level'] > $last['level']) {  
          
           $usection = $dom->createElement('section');  
           $section->appendChild($usection);  
           $sectitle = $dom->createElement('title', htmlentities($item['name']));  
           $usection->appendChild($sectitle);  
          
          }//end if  
          
          $last=$item;  
          
        }//end foreach  
          
        
        

        Damit bin ich jetzt soweit, dass Level 2 und 3 korrekt abgebildet werden. Alle Einträge Level 4 werden wie Level 3 behandelt. D.h. für jedes tiefere Level muss ein neuer DOM-Eintrag vorgenommen werden, der dann auch für ein noch tieferes Level zur Verfügung steht.

        Also Benennen wir mal um: $section = $section2 und $usection = $section3. Und für jedes tiefere Level also $section4, $section5 etc. Kann man eine Variable wie einen String zusammensetzen, um sie später wieder zu verwenden?

        Gruß,
        Leeloo

        --
        "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
        1. Hallo,

          juchu, geschafft, es klappt :-))) Die Lösung: Ein Array basteln. Die Keys darin kann man ja dynamisch ändern *g*

            
          $last = array("level"=>1);  
            
          $sections = array();  
            
          foreach($nodes AS $key=>$item) {  
            
           # Oberkapitel  
           if ($item['level'] == 2) {  
            $section['section2'] = $dom->createElement('section');  
            $article->appendChild($section['section2']);  
            $sectitle = $dom->createElement('title', htmlentities($item['name']));  
            $section['section2']->appendChild($sectitle);  
            
           }elseif ($item['level'] > $last['level']) {  
            $section['section'.$item['level']] = $dom->createElement('section');  
            $section['section'.$last['level']]->appendChild($section['section'.$item['level']]);  
            $sectitle = $dom->createElement('title', htmlentities($item['name']));  
            $section['section'.$item['level']]->appendChild($sectitle);  
            
           }//end if//end if  
            
           $last=$item;  
            
          }//end foreach  
          
          

          ich hoffe mal, das haut auch hin für ewig tiefe Einträge.

          Danke für die Anregungen.

          Gruß,
          Leeloo

          --
          "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
  2. Hallo!

    Da du dein Problem nicht klar beschrieben hast, hilft dir vielleicht auch allein die Problembeschreibung (wenn ich dich denn richtig verstanden habe).

    1. Dein Array ist nicht ganz in der richtigen Ordnung, wenn man die erwünschte Anzeige bedenkt, weil 1.1.1 nach 1.2 kommt (allerdings halte ich das für einen Tippfehler, weil das XML anders aussieht. Du meinst 1.2.1?
    2. Wenn es in der richtigen Ordnung ist, dann ist es doch ganz einfach zu realisieren, oder steh jetzt ich auf dem Schlauch?
    Einfach: Für jedes Array-Element öffnest du eine Section und merkst dir sein Level.
    Wenn das nächste geöffnet wird, vergleichst du gemerktes und neues Level:
    Ist es kleiner wird eine neue Section geöffnet. Ist es gleich oder größer, dann schließt du diese Section und die bereits offene.

    d.h

      
    foreach($nodes AS $node) {  
     extract($node);  
    if($merke=($level-1)) echo "</section></section>";  
    elseif($merke=$level) echo "</section>";  
    // etc. also kann man auch allgemeiner schreiben, jetzt kein bock  
    echo  "<section>  
        <title>$name</title>  
        <para>TEXT</para>";  
     $merke = $level;  
    }  
    
    

    Das ist an sich nicht so hilfreich, aber der Grundgedanke ist klar, oder?
    Er lautet: Merk dir, was offen ist, und guck ob du es schließen musst.

    Gruß,
    Ruben

    1. Hallo,

      danke für deine Antwort.

      Da du dein Problem nicht klar beschrieben hast, hilft dir vielleicht auch allein die Problembeschreibung (wenn ich dich denn richtig verstanden habe).

      Okay, die Frage oder das Problem lautet:
      Wie kriege ich den MySQL-Baum (Nested Sets) in einen XML-Baum umgewandelt?

      1. Dein Array ist nicht ganz in der richtigen Ordnung, wenn man die erwünschte Anzeige bedenkt, weil 1.1.1 nach 1.2 kommt (allerdings halte ich das für einen Tippfehler, weil das XML anders aussieht. Du meinst 1.2.1?

      Huch, einfach nur vertippt. Sorry ...

      foreach($nodes AS $node) {
      extract($node);
      if($merke=($level-1)) echo "</section></section>";
      elseif($merke=$level) echo "</section>";
      // etc. also kann man auch allgemeiner schreiben, jetzt kein bock
      echo  "<section>
          <title>$name</title>
          <para>TEXT</para>";
      $merke = $level;
      }

      
      >   
      > Das ist an sich nicht so hilfreich, aber der Grundgedanke ist klar, oder?  
      > Er lautet: Merk dir, was offen ist, und guck ob du es schließen musst.  
        
      Jo, auch ne Möglichkeit. Möchte aber halt DOM benutzen und nicht Strings.  
        
      Gruß,  
      Leeloo
      
      -- 
      "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra