[PHP/XML] Sitemap & Seitenverwaltung

flaschenkind

Well-known member
ID: 118459
L
20 April 2006
4.507
337
Gibt es eine fertige Klasse (o.ä.), die eine XML Sitemap auslesen kann?
Ich möchte, so wie hier https://www4.klamm.de/forum/showthread.php?t=6712, die Seitenverwaltung über XML machen.
Allerdings habe ich nicht die meistens Erfahrungen mit PHP und XML.
Ich hab jetzt den halben Nachmittag an nem Script gebastelt, was jetzt halbwegs geht, aber es geht max. bis in eine Unterkategorie und zwei Kategorieren hinter einander gehen auch noch nicht.
Wenn es keine fertige Klasse (o.ä.) gibt, werde ich wohl mal meinen Code hier posten und um Hilfe bitten ;) (dann muss ich den Code nur erstmal schöner machen, das was ich da zusammen geschrieben hab ist peinlich :mrgreen:)
 
hast du php5 zurverfügung? dann mach dich mal über simplexml schlau...
Kenn ich, aber bei der Strukturierung find ich das trotzdem etwas kompliziert :-?
Achja, ich weiß wieder, weswegen das so kompliziert war ;)
Ich hatte oben Sites, dann ne Section und dann wieder Sites, aber die Section war bei einem print_r() immer unten, also konnte ich das auch vergessen, weil ich das ja in der Reihenfolge wie in der XML Datei haben wollte.
 
Zuletzt bearbeitet:
Falls es Dir hilft, hier mal die Funktionen zum XML-Parsen, die ich damals eingesetzt habe:
PHP:
/* XML-Funktionen - uncommented */

    var $section = Array();
    var $access = Array('any');
    var $cache = Array(null);
    var $description = Array();
    var $site = null;
    var $tagstack = Array();
    var $value = null;

    function startElement($parser, $name, $attributes) {
      array_push($this->tagstack, $name);
      switch ($name) {
        case 'SECTION':
          $name = empty($attributes['NAME'])?'':$attributes['NAME'];
          if (in_array($name, $this->section))
            trigger_error('Section already defined');
          array_push( $this->section, $name );
          array_push( $this->access, empty($attributes['ACCESS']) ? end($this->access) : $attributes['ACCESS'] );
          array_push( $this->cache, empty($attributes['CACHE']) ? null : $attributes['CACHE'] );
          break;
        case 'SITE':
          $path = implode( '/', $this->section );
          if (!empty($path) and $path[0]=='/')
            $path = substr($path, 1);
          $this->site = Array();
          $this->site['section'] = $path;
          $this->site['name'] = empty($attributes['NAME']) ? null : $attributes['NAME'];
          $this->site['access'] = empty($attributes['ACCESS']) ? end($this->access) : $attributes['ACCESS'];
          $this->site['cache'] = empty($attributes['CACHE']) ? end($this->cache) : $attributes['CACHE'];
          $this->site['description'] = empty($attributes['DESCRIPTION']) ? null : $attributes['DESCRIPTION'];
          $this->site['short'] = empty($attributes['SHORT']) ? null : $attributes['SHORT'];
          break;
        default:
          break;
      }
    }

    function endElement($parser, $name) {
      switch ($name) {
        case 'SECTION':
          if (empty($this->section)) {
            trigger_error('No open section');
            break;
          }
          array_pop($this->section);
          array_pop($this->access);
          array_pop($this->cache);
          break;
        case 'SITE':
          if (empty($this->site['name'])) {
            trigger_error('No name for site');
            break;
          }
          $this->_sitemap[$this->site['section']][$this->site['name']] = $this->site;
          $this->site=null;
          break;
        default:
          if (empty($this->site))
            break;
          $tag = strtolower(end($this->tagstack));
          if (empty($this->value) and !empty($this->site[$tag]))
            unset($this->site[$tag]);
          $this->site[$tag] = chop($this->value);
          break;
      }
      array_pop($this->tagstack);
    }
    function characterData($parser, $data) {
      $this->value = $data;
    }
    function defaultHandler($parser, $data) {
    }

    function parseSitemapXML($filename) {
      $cacheName = CACHEDIR.basename($filename).'.cached';
      if (file_exists($cacheName) && filemtime($cacheName)>filemtime($filename)) {
        $data = file_get_contents($cacheName);
        $sitemap = gzuncompress($data);
        $this->_sitemap = unserialize($sitemap);
        return true;
      }
      $this->_sitemap = Array();
      if (!file_exists($filename))
        return false;
      $content = file_get_contents($filename);
      $xmlparser = xml_parser_create('ISO-8859-1');
      xml_parser_set_option($xmlparser, XML_OPTION_CASE_FOLDING, 1);

      xml_set_element_handler($xmlparser, Array(&$this, 'startElement'), Array(&$this, 'endElement'));
      xml_set_character_data_handler($xmlparser, Array(&$this, 'characterData'));
      xml_set_default_handler($xmlparser, Array(&$this, 'defaultHandler'));

      $result = xml_parse($xmlparser, $content, true);
      if (!$result) {
        $error = sprintf('Sitemap Parse error %d: %s at line %d row %d (Tag: %s)',
                         xml_get_error_code($xmlparser), xml_error_string($xmlparser),
                         xml_get_current_line_number($xmlparser), xml_get_current_column_number($xmlparser),
                         end($this->tagstack));
        trigger_error($error);
        return false;
      }
      xml_parser_free($xmlparser);

      $sitemap = serialize($this->_sitemap);
      $data = gzcompress($sitemap, 9);
      if (function_exists('file_put_contents'))
        file_put_contents($cacheName, $data);
      else {
        $fp = fopen($cacheName, 'w+');
        fwrite($fp, $data);
        fclose($fp);
      }
      return true;
    }
Man möge mir die schlechte Formatierung verzeihen. Ich find grad keine schickere Variante des Ganzen.

Ich würd Dir eh dazu raten, den Code nur als Orientierungshilfe zu nehmen. Wenn Du PHP5 hast, nimm wirklich SimpleXML, damit geht das um einiges einfacher. Dieses hier ist halt PHP4-kompatibel.

Und ganz wichtig: Vergiss RegExp zum Parsen von XML. ;)
 
Ok, thx :)
Ich werde es mal testen.
Und wenn ich RegExp vergessen kann, dann kann ihc meinen Code in die Tonne kloppen :ugly:
 
Fürs Parsen von XML sind RegExp einfach nicht flexibel genug. Da bauste Dir ein Riesenkonstrukt auf, das Dir später bei kleinen Änderungen das Genick brechen wird, weil Du dann im schlimmsten Fall wieder alles umschreiben darfst.

Da sind die XML-Parser-Funktionen der verschiedenen PHP-Bibliotheken einfach besser für geeignet.
 
OK, hab das mal getestet und das funktioniert auch soweit. Allerdings hab ich es soweit auch selber geschafft, nur halt nicht als Arrays.
Code:
Array
(
    [] => Array
        (
            [Startseite] => Array
                (
                    [section] => 
                    [name] => Startseite
                    [access] => any
                    [cache] => 
                    [description] => 
                    [short] => 
                )

            [News] => Array
                (
                    [section] => 
                    [name] => News
                    [access] => any
                    [cache] => 
                    [description] => Neuigkeiten
                    [short] => 
                )

            [Impressum] => Array
                (
                    [section] => 
                    [name] => Impressum
                    [access] => any
                    [cache] => 
                    [description] => 
                    [short] => 
                )

        )

    [user] => Array
        (
            [Benutzerbereich] => Array
                (
                    [section] => user
                    [name] => Benutzerbereich
                    [access] => any
                    [cache] => 
                    [description] => 
                    [short] => 
                )

            [Login] => Array
                (
                    [section] => user
                    [name] => Login
                    [access] => public
                    [cache] => 
                    [description] => 
                    [short] => 
                )

            [Verwaltung] => Array
                (
                    [section] => user
                    [name] => Verwaltung
                    [access] => private
                    [cache] => 
                    [description] => 
                    [short] => 
                )

        )

)
XML:
Code:
<sitemap>
  <site name="Startseite" key="home"/>
  <site name="News" key="news" description="Neuigkeiten"/>
  <section name="user">
     <site name="Benutzerbereich" key="home"/>
     <site name="Login" key="login" access="public"/>
     <site name="Verwaltung" key="profile" access="private" />
  </section>
  <site name="Impressum" key="imprint"/>
</sitemap>
(ist deiner, tleilax, allerdings ist das Impressum unter der Section)

Jetzt hab ich die Sections wieder unten in dem Array, aber ich möchte das gerne in der selben Reihenfolge haben, wie in der XML Datei. Ist das irgentwie möglich?
Langsam verzweifel ich an diesen XML-Dateien :ugly:
 
Nope, das ist nicht möglich, wenn ich Dich richtig verstanden habe. Du willst "Impressum" unter der Section "user" haben oder? Der Eintrag "Impressum" wird der Section "" zugewiesen, da er auf Rootebene des Dokuments steht. Da geht kein Weg dran vorbei, wenn Du nicht die gesamte Struktur umbauen willst.
 
Nope, das ist nicht möglich, wenn ich Dich richtig verstanden habe. Du willst "Impressum" unter der Section "user" haben oder? Der Eintrag "Impressum" wird der Section "" zugewiesen, da er auf Rootebene des Dokuments steht. Da geht kein Weg dran vorbei, wenn Du nicht die gesamte Struktur umbauen willst.
Mist, denn das hatte ich vorher in etwa genauso mit simplexml gelöst :-?
Ich glaub ich muss doch auf MySQL zurückgreifen :(