Ankündigung

Einklappen
Keine Ankündigung bisher.

Menü aus XML erzeugen, Syntax-Problem Array-Aufbau

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Menü aus XML erzeugen, Syntax-Problem Array-Aufbau

    Hallo allerseits,

    ich möchte aus einer XML-Datei (1) über eine php-Klasse (2) ein Array (3) erzeugen. In einen Array bekomme ich auch alles ganz gut, jedoch weiß ich nicht, wie ich in der Methode "buildMenuStructure" für die Kinder in eine tiefere Ebene des Array komme, so dass das Modell wie in 3 entsteht. Ich habe immer alle Menüelemente auf einer Ebene - die SubElemente sind also nicht als Children zugeordnet...

    Ich hoffe, dass mich der eine oder andere verstanden hat und mir helfen kann! Wäre sehr geil

    Ach so: Falls das ein Anfänger-Problem ist, bitte einfach verschieben!

    Viele Grüße,
    André


    1. XML-Datei
    PHP-Code:
    <?xml version="1.0"?>
    <menu>
        <menuElement view="defaultview" url=""/>
        <menuElement view="systems" url="?op=systems">
            <menuSubElement view="systemgroups" url="?op=systemgroups"/>
            <menuSubElement view="systemoverview" url="?op=systemOverview"/>
            <menuSubElement view="addsystem" url="?op=addSystem"/>
            <menuSubElement view="import" url="?op=import"/>
        </menuElement>
        <menuElement view="mylandscape" url="?op=mylandscape">
            <menuSubElement view="personaldata" url="?op=personaldata"/>
            <menuSubElement view="responsibilities" url="?op=responsibilities"/>
            <menuSubElement view="subscriptions" url="?op=subscriptions"/>
        </menuElement>
    </menu>
    2. Ausschnitt der php-Klasse
    PHP-Code:
    public function buildMenuAsArray($whichMenu$activeView) {
        
        
    // Menueexistenz feststellen
        
    if(!array_key_exists($whichMenu$this->map)) {
            die(
    "The selected menu doesn't exist in the menuMap.");
        } 
        
        
    // XML-Datei als DOM-Objekt einlesen
        // :TODO: Datei-Existenz pruefen...
        
    $this->menuDom = new domDocument();
        
    $this->menuDom->preserveWhiteSpace false;
        
    $this->menuDom->load($this->map[$whichMenu]);
        
        
    // Mit der ersten Menue-Ebene starten...
        
    $highestElements $this->menuDom->getElementsByTagName('menuElement'); 
        foreach(
    $highestElements as $highestElement) {
            
    $this->buildMenuStructure($highestElement$this->menu$activeView);
        }
    }

    private function 
    buildMenuStructure($menuElement$menu$activeView) {
        
    $active = ($menuElement->getAttribute("view") == 
            
    strtolower($activeView)) ? true false;
        
    $gotChildren $menuElement->hasChildNodes();
        
    $this->menu[] = array('view' => $menuElement->getAttribute("view"), 
                              
    'url' => $menuElement->getAttribute("url"),
                              
    'active' => $active
                              
    'gotChildren' => $gotChildren);
        if(
    $gotChildren) {
            
    $childElements $menuElement->childNodes;
            foreach(
    $childElements as $childElement) {
                
    $this->buildMenuStructure($childElement$menu$activeView);
            }        
        }

    3. gewünschter Aufbau des Array
    PHP-Code:
    $menu[menuItem][url] = "bla..."
                   
    [view] = "blubb..."
                   
    [active] = 1
                   
    [gotChildren] = 1
                   
    [childActive] = 1
                   
    [children][menuItem] ... usw. (alle SubElementeStruktur wie oben) ... 

  • #2
    Hallo André.

    Ich hab mir deinen Code und dein Problem nicht näher angeschaut. Ich hab aber kürzlich auch - um die Dom-Funktionen mal kennen zu lernen - eine kleine Klasse geschrieben, um aus einer XML-"Sitemap" ein Menü zu erzeugen. Allerdings mache ich da gleich wieder ein XML-Dokument raus, anstatt es in ein Array zu schreiben. Aber vielleicht kannst du da was für dich rausziehen. Ob es schön, schnell etc. weiß ich nicht bzw. wage ich zu bezweifeln. Ist eben mein erster Gehversuch mit den Dom-Funktionen.

    Hier mal der Code:
    sitemap.xml
    PHP-Code:
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE sitemap [
       <!ELEMENT sitemap (page*)>
       <!ATTLIST page id ID #REQUIRED>
       <!ATTLIST page title CDATA #REQUIRED>
       <!ELEMENT page (page*)>
    ]>
    <sitemap>
        <page id="home" title="Startseite" />
        <page id="about" title="Ueber uns">
            <page id="company" title="Firma" />
            <page id="team" title="Team" />
        </page>
        <page id="imprint" title="Impressum" />
    </sitemap>
    index.php
    PHP-Code:
    <?php
    error_reporting
    (E_ALL);
    require_once 
    'class.Menu.php';

    $sDefaultPage 'home';
    $sSitemapFile 'sitemap.xml';

    $sCurrPage = isset($_GET['page']) ? $_GET['page'] : $sDefaultPage;

    $Sitemap = new DOMDocument();
    $Sitemap->preserveWhiteSpace false;
    $Sitemap->load($sSitemapFile);

    $Document = new DOMDocument();
    $Document->preserveWhiteSpace false;
    $Document->formatOutput true;

    try {
        
    $Menu = new Menu($Document$Sitemap$sCurrPage);
        
    $MainMenu $Menu->createMainMenu();
        
    $BredcrumbsMenu $Menu->createBreadcrumbs();

    } catch (
    Exception $e) {
        die(
    'Caught exception: ' $e->getMessage());
    }
    header('Content-type: text/html; charset=utf-8');
    print 
    $Document->saveXML();
    ?>
    class.Menu.php
    PHP-Code:
    <?php

    class Menu
    {
        private 
    $Document NULL;
        private 
    $Sitemap  NULL;
        private 
    $Path     NULL;
        private 
    $CurrNode NULL;
        private 
    $CurrPath NULL;

        public function 
    __construct(DOMDocument $DocumentDOMDocument $Sitemap$sCurrPageId)
        {
            
    $this->Document $Document;
            
    $this->Sitemap  $Sitemap;
            
    $this->Path     = new DOMXPath($Sitemap);

            if (!
    $this->CurrNode $this->Sitemap->getElementByID($sCurrPageId))
                throw new 
    Exception('Page not found in sitemap.xml');
            
    $this->CurrPath $this->getPath($this->CurrNode);
        }

        public function 
    createMainMenu($MenuTree=false) {

            static 
    $i 0;

            if (
    false === $MenuTree) {
                
    $MenuTree $this->Document->appendChild(
                    
    $this->Document->createElement('div'));
            }

            
    $List $MenuTree->appendChild(
                
    $this->Document->createElement('ul'));

            
    $bNodeExists $this->CurrPath->length $i;
            
    $sQuery = ($bNodeExists)
                ? 
    'preceding-sibling::page|self::page|following-sibling::page'
                
    'child::page';
            
    $CurrNode = ($bNodeExists)
                ? 
    $this->CurrPath->item($i)
                : 
    $this->CurrPath->item($i-1);
            
    $Siblings $this->Path->query($sQuery$CurrNode);

            foreach (
    $Siblings as $Node) {

                
    $sTitle $Node->getAttribute('title');
                
    $sId    $Node->getAttribute('id');

                
    $Item $List->appendChild(
                    
    $this->Document->createElement('li'));

                if (
    $Node !== $CurrNode) {
                    
    $Href $Item->appendChild(
                        
    $this->Document->createElement('a'$sTitle));
                    
    $Href->setAttribute('href'"?page=$sId");
                } else {
                    
    $Item->appendChild(
                        
    $this->Document->createElement('strong'$sTitle));
                }
                if (
    $Node === $CurrNode && $this->hasChildren($Node)) {
                    
    $i++;
                    
    $this->createMainMenu($Item);
                }
            }
            return 
    $MenuTree;
        }

        public function 
    createBreadcrumbs($MenuTree=false)
        {
            if (
    false === $MenuTree) {
                
    $MenuTree $this->Document->appendChild(
                    
    $this->Document->createElement('div'));
            }

            
    $List $MenuTree->appendChild(
                
    $this->Document->createElement('ul'));

            foreach (
    $this->CurrPath as $Node) {

                
    $sTitle $Node->getAttribute('title');
                
    $sId    $Node->getAttribute('id');

                
    $Item $List->appendChild(
                    
    $this->Document->createElement('li'));

                if (
    $Node !== $this->CurrNode) {
                    
    $Href $Item->appendChild(
                        
    $this->Document->createElement('a'$sTitle));
                    
    $Href->setAttribute('href'"?page=$sId");
                } else {
                    
    $Item->appendChild(
                        
    $this->Document->createElement('strong'$sTitle));
                }
            }
            return 
    $MenuTree;
        }

        private function 
    getPath($Node)
            {
            return 
    $this->Path->query('ancestor-or-self::page'$Node);
        }

        private function 
    hasChildren($Node)
            {
            
    $Children $this->Path->query('child::page'$Node);
            return 
    $Children->length 0;
        }
    }
    ?>
    Liebe Grüße,
    Basti

    Kommentar


    • #3
      Hi Basti,

      erstmal Danke für Deinen Beitrag! Das Ergebnis, was also am Ende rauskommt, wäre noch mal ganz interessant gewesen :wink:

      Ich habe mein Problem inzwischen ein wenig anders gelöst (und es funktioniert auch...).
      Falls es jemanden interessiert (Kritik ist ausdrücklich erwünscht):

      XML-Datei:
      PHP-Code:
      <?xml version="1.0"?>
      <menu>
          <menuElement view="defaultview" url=""/>
          <menuElement view="systems" url="?op=systems">
              <menuElement view="systemgroups" url="?op=systemgroups"/>
              <menuElement view="systemoverview" url="?op=systemOverview">
                  <menuElement view="systemgroups2" url="?op=systemgroups2"/>
                  <menuElement view="systemgroups3" url="?op=systemgroups3"/>
              </menuElement>
              <menuElement view="addsystem" url="?op=addSystem"/>
              <menuElement view="import" url="?op=import"/>
          </menuElement>
          <menuElement view="mylandscape" url="?op=mylandscape">
              <menuElement view="personaldata" url="?op=personaldata"/>
              <menuElement view="responsibilities" url="?op=responsibilities"/>
              <menuElement view="subscriptions" url="?op=subscriptions"/>
          </menuElement>
      </menu>

      Menü-Klasse (die menuMap ist ja klar...):
      PHP-Code:
      <?php
      /*
       * Systemlandschaft: class/template/menu.class.php
       * Autor: Andre Kolell 
       * Erstellt: 19.10.2005, 20:54
       *
       * Kurzbeschreibung:
       * Diese Klasse liest eine XML-Menuestruktur ein und stellt diese dann in der
       * gewuenschten Form (bisher ist lediglich "Array" implementiert) bereit.
       */
       
      class Menu {
          
          
      // Zuordnungen zwischen Menues und einzubindenden XML-Dateien
          // (jedes Menue, z.B. Hauptmenue, Shortcuts, etc. hat seine eigene Datei)
          
      private $map;
          
          
      // Das "fertige" Menue (bisher ist lediglich "Array" implementiert)
          
      private $menu;
          
          
      // Aktueller View 
          
      private $activeView;        // als String, z.B. "defaultView"
          
      private $activeViewKey;        // als Key in einem Array, z.B. "4"


          
          // Konstruktor. $activeView entspricht der aus vielen Webprojekten bekannten 
          // "$display"-Variable. Zum Zeitpunkt der Erstellung dieses Menues muss also
          // der aktuelle View bereits bekannt sein.
          
      function __construct($activeView) {
              
              
      // Zuordnungen zwischen Menues und einzubindenden XML-Dateien bereitstellen
              
      include_once("class/template/menu/menumap.properties.php");
              
      $this->map $menuMap;
              
              
      // Aktiven View belegen
              
      $this->activeView $activeView;
          }



          
      // Erzeugt das Menue ($whichMenu) als Array aus der XML-Datei
          
      public function buildMenuAsArray($whichMenu) {
              
              
      // Menueexistenz feststellen
              
      if(!array_key_exists($whichMenu$this->map)) {
                  die(
      "The selected menu doesn't exist in the menuMap.");
              } 
              
              
      // XML-Datei als DOM-Objekt einlesen
              // :TODO: Datei-Existenz pruefen...
              
      $menuDom = new domDocument();
              
      $menuDom->preserveWhiteSpace false;
              
      $menuDom->load($this->map[$whichMenu]);
              
              
      // Wurzelelement "menu" und dessen Kinder (erste Menueebene) holen
              
      $rootElementNodeList $menuDom->getElementsByTagName('menu');
              
      $rootElement $rootElementNodeList->item(0);
              
      $firstMenuLevel $rootElement->childNodes;
              
              
      // Komplette Baumstruktur erzeugen, aktives Element kennzeichnen (und merken)
              
      foreach($firstMenuLevel as $menuElement) {
                  
      $this->buildMenuAsArrayAddElement($menuElement00);
              }    

              
      // Ist ein Menuepunkt (View) aktiv, und ist dieser Menuepunkt in einer
              // tieferen Ebene als der Ersten, muss die Baumstruktur geoffnet werden
              
      if(isset($this->activeViewKey) && 
                      
      $this->menu[$this->activeViewKey]['hierachy'] > 0) {
                  
      $this->buildMenuAsArrayOpenRelevantItems($this->activeViewKey);
              }
          }    

          
      // Fuegt dem Array-Menue ein Menueelement hinzu 
          
      private function buildMenuAsArrayAddElement($menuElement$crntLevel$parentKey) {
              if(
      $menuElement->getAttribute("view") == strtolower($this->activeView)) {
                  
      $activeView true;
                  
      $this->activeViewKey count($this->menu);
              } else {
                  
      $activeView false;    
              }
              
      $gotChildren $menuElement->hasChildNodes();
              
      $this->menu[] = array('view' => $menuElement->getAttribute("view"), 
                                    
      'url' => $menuElement->getAttribute("url"),
                                    
      'hierachy' => $crntLevel,
                                    
      'parent' => $parentKey,
                                    
      'activeView' => $activeView
                                    
      'open' => false);
              if(
      $gotChildren) {
                  
      $crntLevel++;
                  
      $thisElementsKey = (count($this->menu)-1);
                  
      $childElements $menuElement->childNodes;
                  foreach(
      $childElements as $childElement) {
                      
      $this->buildMenuAsArrayAddElement($childElement$crntLevel$thisElementsKey);
                  }        
              }
          }

          
      // Oeffnet die gleich- und uebergeordnete Struktur eines Menueelementes
          
      private function buildMenuAsArrayOpenRelevantItems($parentKey) {
              
              
      // Aktuelles Menueelement und Elemente gleicher Ebene oeffnen
              // :TODO: Es geht sicherlich einfacher!?
              
      for($i 0$i count($this->menu); $i++) {
                  if(
      $this->menu[$i]['parent'] == $parentKey) {
                      
      $this->menu[$i]['open'] = true;
                  }    
              } 
              
              
      // Sofern es sich bei dem aktuellen Menueelement nicht um eines der ersten 
              // Ebene handelt, wird die Methode nun mit dem Elternelement aufgerufen        
              
      if($this->menu[$parentKey]['hierachy'] > 0) {
                  
      $this->buildMenuAsArrayOpenRelevantItems($this->menu[$parentKey]['parent']);            
              }    
          }

          
      // Gibt das Menue zurueck 
          
      public function getMenu() {
              return 
      $this->menu;
          }

      ?>

      Folgendes Array entsteht ($activeView = "responsibilities"):
      PHP-Code:
      Array
      (
          [
      0] => Array
              (
                  [
      view] => defaultview
                  
      [url] => 
                  [
      hierachy] => 0
                  
      [parent] => 0
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      1] => Array
              (
                  [
      view] => systems
                  
      [url] => ?op=systems
                  
      [hierachy] => 0
                  
      [parent] => 0
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      2] => Array
              (
                  [
      view] => systemgroups
                  
      [url] => ?op=systemgroups
                  
      [hierachy] => 1
                  
      [parent] => 1
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      3] => Array
              (
                  [
      view] => systemoverview
                  
      [url] => ?op=systemOverview
                  
      [hierachy] => 1
                  
      [parent] => 1
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      4] => Array
              (
                  [
      view] => systemgroups2
                  
      [url] => ?op=systemgroups2
                  
      [hierachy] => 2
                  
      [parent] => 3
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      5] => Array
              (
                  [
      view] => systemgroups3
                  
      [url] => ?op=systemgroups3
                  
      [hierachy] => 2
                  
      [parent] => 3
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      6] => Array
              (
                  [
      view] => addsystem
                  
      [url] => ?op=addSystem
                  
      [hierachy] => 1
                  
      [parent] => 1
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      7] => Array
              (
                  [
      view] => import
                  
      [url] => ?op=import
                  
      [hierachy] => 1
                  
      [parent] => 1
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      8] => Array
              (
                  [
      view] => mylandscape
                  
      [url] => ?op=mylandscape
                  
      [hierachy] => 0
                  
      [parent] => 0
                  
      [activeView] => 
                  [
      open] => 
              )

          [
      9] => Array
              (
                  [
      view] => personaldata
                  
      [url] => ?op=personaldata
                  
      [hierachy] => 1
                  
      [parent] => 8
                  
      [activeView] => 
                  [
      open] => 1
              
      )

          [
      10] => Array
              (
                  [
      view] => responsibilities
                  
      [url] => ?op=responsibilities
                  
      [hierachy] => 1
                  
      [parent] => 8
                  
      [activeView] => 1
                  
      [open] => 1
              
      )

          [
      11] => Array
              (
                  [
      view] => subscriptions
                  
      [url] => ?op=subscriptions
                  
      [hierachy] => 1
                  
      [parent] => 8
                  
      [activeView] => 
                  [
      open] => 1
              
      )


      Dieses kann dann z.B. an Smarty übergeben und dort weiterverarbeitet werden...

      Hoffe auf Feedback!

      Viele Grüße,
      André

      Kommentar


      • #4
        Zitat von creative-w3.de
        Das Ergebnis, was also am Ende rauskommt, wäre noch mal ganz interessant gewesen :wink:
        ...das sieht bei dir (hoffentlich) nicht anders aus, als bei mir. Aber ... okay :wink: Hier eine Demo:

        http://coyserve.de/dom-menu.php

        Das muss man natürlich dann noch mit Atrributen versehen, um es mit CSS dann in die richtige Form zu bringen. Und ... ich seh grad, dass man "Über uns" nicht klicken kann, wenn einer der Unterpunkte "aktiv" ist.

        Basti

        Kommentar


        • #5
          ... wenn http://coyserve.de/dom-menu.php das Ergebnis von http://coyserve.de/sitemap.xml ist, klappt es wohl noch nicht so gut!?

          - Startseite
          - Über uns
          - Impressum
          - Startseite

          Kommentar


          • #6
            Schau dir den Quellcode doch mal an, ich hab ihn doch hier abgebildet. Die ersten 3 Punkt sind das Hauptmenü (und beim Klick auf "Über uns" werden die Punke "Firma" und "Produkte" oder so sichtbar) die zweite Liste ist ein Breadcrumbs-Menü.

            Wie geschriben: Ich kann dir nicht anbieten, was du suchtest (und inzwischen ja scheinbar selbst gelöst hast), sondern einen Code, wie ich ein ähnliches Problem gelöst hab. Wenn du damit was anfangen willst, dann schau dir den Code halt auch an und leite nicht von dem natürlich anderen Ergebnis (da andere Aufgabenstellung) ab, dass es nicht so funktioniert, wie du es dir vorstellst.

            Basti

            Kommentar


            • #7
              Hi Basti,

              du hast Recht. Ich hatte gestern nur kurz auf http://coyserve.de/dom-menu.php gesehen und den 2. Punkt "Startseite" für einen Punkte des Menüs gehalten. Natürlich funktioniert es... sorry.

              Viele Grüße,
              André

              Kommentar


              • #8
                Hallo.

                Ich hab jetzt nochmal zwei Fehler rausgenommen (statischen Zähler zurücksetzen und die genannte Verlinkung von "Über uns") und die Klasse noch ein wenig erweitert (css-Klassen-Angabe für die Menüs und Änderun der Ausweisung des "aktiven Elements"). Hier mal ein Beispiel, wie das dann mit ein wenig CSS gestaltet werden könnte (habs mir nur im FF angeschaut):

                http://coyserve.de/dom-menu2.php

                Das Design der Klasse ist natürlich sehr fragwürdig (z.B. CSS-Klassen hier feszulegen). Der Ausgangspunkt war jedoch eine Schulung bei einem Webdesigner, in der wir ein eifaches "Frames-Workaround" angefangen haben, dass ich dann eben, um DOM kennen zu lernen ein wenig erweitert hab.

                Basti

                Kommentar

                Lädt...
                X