Synopsis: [URL Manager Pro 3.4.1] [XML Bookmark Exchange Language (XBEL)] [XBEL Resource Page] [O'Reilly Programmieren mit PHP]
Browser können eine HTML-Ausgabe der Bookmarks erzeugen -aber das ist zur Verwaltung nicht praktisch. Für Mac OS X gibt es eine Software URL Manager Pro, die eine systemweite Verwaltung von URL erlaubt, besonders praktisch ist die Organisation in Ordnern mit Komentaren usw.. Als Export kommt neben HTML auch Text mit Tab und XBEL in Frage.
Bookmark-Quelledatei: elektro.text / PHP-Skript von Daniel Beck:
<?php /* Datei laden. Format: "TITEL URL BESCHREIBUNG" (trennung durch tabs) oder "TITEL URL" oder "- " ("minus tab" wird zu ner <hr/>) für php < 4.3.0: join('', file('text.txt')); */ $text = file_get_contents('text.txt'); $text = str_replace("\r", "\n", $text); // Mac macht \r statt \n $text = str_replace("\n-\t", "\n<hr/>\n", $text); // Erstmal alle "- " zu <hr/> machen: /* Links mit Titel und Beschreibung matchen und umwandeln. Keine Zeilenumbrüche in der Beschreibung */ $text = preg_replace('#(.+)\\t(.+)\\t(.+)#i', '<a href="\\2">\\1</a> \\3</p>' . "\n", $text); /* Links mit Titel matchen und umwandeln, die mit Beschreibung wurden ja schon geändert. */ $text = preg_replace('#(.*)\\t(.*)#i', '<p><a href="\\2">\\1</a></p>' . "\n", $text); echo $text;// Ausgabe ?>
Elektro-Bastel 5 Watt Lumileds Luxeon Star von Diana Electronic Superhelle LEDs ElektrowiderstŠnde - Zusatzinfos WiderstŠnde im KFZ ElektrowiderstŠnde Tankanzeige KFZ Messgeber im Tank Fuellstandanzeige Digitale Erfassung des FŸllstandes |
Ist leider nicht so berauschend, vor allem die Umlaute machen Ärger trotz UTF-8. Ist auch nicht besonders flexibel. Daher nun die volle Ladung:
Bookmark-Quelledatei: elektro.xbel
<?xml version="1.0"?> <!DOCTYPE xbel> <!-- Created by URL Manager Pro - http://www.url-manager.com --> <xbel version="1.0"> <folder folded="no"> <title>Elektro-Bastel</title> <bookmark href="http://www.dianaelectronic.de/led/led20.htm"> <title>5 Watt Lumileds Luxeon Star von Diana Electronic</title> <desc>Superhelle LEDs</desc> </bookmark> <bookmark href="http://www.physik-am-auto.de/elwi/elwi_z1.htm"> <title>Elektrowiderstände - Zusatzinfos</title> <desc>Widerstände im KFZ</desc> </bookmark> <bookmark href="http://www.physik-am-auto.de/elwi/"> <title>Elektrowiderstände</title> <desc>Tankanzeige KFZ Messgeber im Tank</desc> </bookmark> <bookmark href="http://homepages.fh-regensburg.de/~hem39093/fuflab/Fuellstandsanzeige.htm"> <title>Fuellstandanzeige</title> <desc>Digitale Erfassung des Füllstandes</desc> </bookmark> </folder> </xbel>
Schickes Format XML Bookmark Exchange Language (XBEL) nur wie krieg ich das nun auf meine Seite?
Lesen hilft: Buch O'Reilly "Programmieren mit PHP" im Beispielteil gibt es Quelltexte zum Download -Kapitel 11 Vers 10 PHP! Beispiel für einen XML-Parser mit PHP..
class BookList { var $parser; function BookList ($filename) { $this->parser = xml_parser_create(); xml_set_object($this->parser, &$this); xml_set_element_handler($this->parser, 'start_element', 'end_element'); xml_set_character_data_handler($this->parser, 'cdata'); xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8'); $x = join("", file($filename)); xml_parse($this->parser, $x); xml_parser_free($this->parser); } function start_element ($p, $element, &$attributes) { $element = strtolower($element); foreach ($attributes as $key => $v){ echo "$element : $key = $v <br>"; } } function end_element ($p, $element) { $element = strtolower($element); echo 'end: ' . $element . '<br>'; } function cdata ($p, $text) { if (strlen($text) > 1 ) echo 'cdata: ' . $text . ' '; } }; $my_library = new BookList ("elektro.xbel"); // main program code
Problem: Das Tag title wird in zwei verschiedenen Zusammenhängen (Kontexten) verwendet:
Somit muss man sich beim Parsen merken was gerade bearbeitet wird.
<?php class BookList { var $parser; var $bookfolder = ''; var $href; var $titel; var $desc; var $cur_tag; function BookList ($filename) { $this->parser = xml_parser_create(); xml_set_object($this->parser, &$this); xml_set_element_handler($this->parser, 'start_element', 'end_element'); xml_set_character_data_handler($this->parser, 'cdata'); xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8'); xml_parse($this->parser, file_get_contents($filename)); xml_parser_free($this->parser); } function start_element ($p, $element, &$attributes) { $element = strtolower($element); $this->cur_tag = $element; switch($element){ case 'folder': $this->bookfolder = 'folder'; break; case 'bookmark': $this->bookfolder = 'bookmark'; $this->href = $attributes['HREF']; break; case 'title' : $this->titel=''; break; case 'desc' : $this->desc=''; break; } } function end_element ($p, $element) { $element = strtolower($element); if ($this->bookfolder == 'folder' && $element == 'title') echo '<h3>'. $this->titel .'</h3>'; if ($element == 'bookmark'){ echo '<p> <a href= "' . $this->href . '">'; if (trim($this->titel)) echo $this->titel; else echo $this->href; echo'</a> ' . $this->desc . '</p>'; $this->titel=''; $this->desc=''; } } function cdata ($p, $text) { if(trim($text)){ switch($this->cur_tag){ case 'title': $this->titel .= $text; break; case 'desc': $this->desc .= $text; break; } } } }; $my_library = new BookList ("elektro.xbel"); ?>
Nun möchte ich mehr Komfort, die Datenstruktur soll OO sein, zunächst eine Analyse der Klassen [http://pyxml.sourceforge.net/topics/xbel/docs/html/public-text.html]. Diese Klassendiagramm-Skizze lässt sich so leider nicht in PHP realisieren, keine abstrakten Klassen... |
/* hier sollte die Klasse Xmain als abstrakte Mutter einiger Klassen stehen, scheint aber in PHP nicht vorgesehen zu sein */ class Separator { function display(){ echo '<hr>'; } } class Xnode { // abstrakte Klasse var $title; //var $info; var $desc; //var $added; } class Folder extends Xnode { var $folded; var $nodes=array(); // Liste der Unterknoten function display(){ echo '<h3>[' . $this->title . '] ' . $this->desc . '</h3>'; if ($this->nodes) foreach ($this->nodes as $n) $n->display(); } } class Bookmark extends Xnode { var $href; //var $visited; //var $modified; function display(){ echo '<p> <a href= "' . $this->href . '"> '; if (trim($this->title)) echo $this->title; else echo $this->href; echo'</a> ' . $this->desc . '</p>'; } } class Xbel extends Xnode { var $parser; var $nodes = array(); var $cur_tag; function Xbel ($filename) { $this->parser = xml_parser_create(); xml_set_object($this->parser, &$this); xml_set_element_handler($this->parser, 'start_element', 'end_element'); xml_set_character_data_handler($this->parser, 'cdata'); xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8'); xml_parse($this->parser, file_get_contents($filename)); xml_parser_free($this->parser); } function start_element ($p, $element, &$attributes) { $element = strtolower($element); $this->cur_tag = $element; switch($element){ case 'folder': case 'xbel': array_push($this->nodes, new Folder()); break; case 'bookmark': $this->bookfolder = 'bookmark'; $bo = new Bookmark(); $bo->href = $attributes['HREF']; array_push($this->nodes, $bo); break; case 'separator': array_push($this->nodes, new Separator()); break; } } function end_element ($p, $element) { $element = strtolower($element); switch($element){ case 'folder': case 'xbel': case 'bookmark': case 'separator': $this->nodes[count($this->nodes)-2]->nodes[] = $this->nodes[count($this->nodes)-1]; array_pop($this->nodes); } } function cdata ($p, $text) { if(trim($text)){ switch($this->cur_tag){ case 'title': $this->nodes[count($this->nodes)-1]->title .= $text; break; case 'desc': $this->nodes[count($this->nodes)-1]->desc .= $text; break; } } } function display(){ // Zeigt alles an echo "<h2> $this->title $this-desc </h2>"; if ($this->nodes) foreach ($this->nodes as $n) $n->display(); } function display_top(){ // Zeigt nur Tiefe 1 an und Ordner werden als Links anzeigt $bu = $this->nodes[0]; foreach ($bu->nodes as $n){ if (get_class($n)=='folder'){ echo '<p> [<a href="'. $_SERVER['PHP_SELF'] . '?sub=' . $n->title . '">'. $n->title . '</a>] ' . $n->desc . '</p>'; } else $n->display(); } } function display_sub($tit){ // Zeigt Unterordner namens $tit an $bu = $this->nodes[0]; foreach ($bu->nodes as $n){ if (get_class($n)!='folder' || $n->title != $tit){ continue; } else{ $n->display(); break; } } } };
To be..