[PHP] BBCode-Listen-Parser: Problem mit preg_replace()

mh1001

Lt. Commander
Registriert
Nov. 2003
Beiträge
2.039
Hallo,

ich habe mich nun einmal entschlosssen, das BBCode-Parsing-System auf meiner Website wieder einmal etwas auszubauen.
Jedoch will das Parsing von Listen nicht so ganz klappen.

Dabei soll folgende Eingabe ("-" dienen nur dazu, dass das Forum die Tags nicht als BBCode interpretiert gehören nicht dazu):
Code:
[-list-]
  [-*-]a
  [-*-]b
  [-*-]c
[-/list-]
im ersten Parsing-Durchlauf in folgendes umgewandelt werden:
Code:
<ul>
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>
Mein Versuch sieht bisher folgendermaßen aus:
PHP:
<?php
$format = preg_replace("#\[list\](.*)\[\*\](.*)\[/list\]#is", "
[list]\\1</li><li>\\2
[/list]", $format);
    $format = preg_replace("#\[list\](.+?)\[/list\]#is", "<ul><li>\\1</li></ul>", $format);
$format = str_replace("<li></li>", "", $format);
?>
Leider scheint dies aber nicht zu funktionieren. So wird zum Beispiel aus folgender Eingabe:
Code:
[-list-]
[-*-]Test #1
[-*-]Test #2
[-*-]und noch nen Listenpunkt
[-/list-]
folgendes:
Code:
<ul><li>
[*]Test #1
[*]Test #2
</li><li>und noch nen Listenpunkt
</li></ul>
Dies ist nun leider nicht die erwartete Ausgabe, da nur das Letzte "[-*-]" in "</li><li>" umgewandelt wird.
Doch wo befindet sich der Fehler? ;)

MfG mh1001
 
Zuletzt bearbeitet:
Nach einigen "Nachforschungen" muss ich nun noch einmal den Thread aus den Tiefen des Forums holen. ;)

Ich habe mich nun noch einmal im PHP-Manual bzgl. des Problems umgesehen. Die Sache ist ganz einfach die, dass preg_replace nach dem ersten Fund die Stelle im String gleich überspringt und keine weiteren Suchen mehr in dieser ausführt, sondern gleich mit der Abarbeitung des Reststrings anfängt.

Soweit, so gut:

Ich habe mich nun einmal daran gemacht, den Code dementsprechend etwas umzuschreiben:
PHP:
     while(preg_match("#\[list\].*\[\*\].*\[/list\]#is", $format))
     {
       $format = preg_replace("#\[list\](.*)\[\*\](.*)\[/list\]#is", "
[list]\\1</li><li>\\2
[/list]", $format);
     }
 
     while(preg_match("#\[list\].*<li>\s</li>.*\[/list\]#is", $format))
     {
       $format = preg_replace("#\[list\](.*)<li>\s</li>(.*)\[/list\]#is", "
[list]\\1\\2
[/list]", $format);
     }
 
     $format = preg_replace("#\[list\](.+?)\[/list\]#is", "<ul><li>\\1</li></ul>", $format);
Nun gibt es aber noch zwei Probleme:

1) Die zweite Schleife soll dazu dienen, leere Listenpunkte, bzw. solche, die nur Whitespace enthalten, zu entfernen.
Allerdings scheint dies preg_replace() nicht zu befolgen und liefert auch solche Listenpunkte wieder zurück.

2) Mit den beiden Schleifen ist das ganze bei längeren Listen doch recht resourcenlastig. Gibt es eine Möglichkeit, den Code irgendwie etwas zu optimieren? Vor allem bei einem später hinzukommenenden 2. Parsing-Gang zur Üperprüfung der korrekten Verschachtelung von Tags käme eine etwas weniger leistungshungrige Methode sehr gelegen.

MfG mh1001

//Edit:

Problem #1 hat sich soeben erledigen lassen. Das ganze war ein Denkfehler. Zum einen kann der Whitespace ja auch aus mehreren Leerzeichen oder ähnlichen bestehen, was sich mit dem "*" beheben lies.
Ebenfalls wurde damit auch gleich der Fall eines komplett leeren Tags ("<li></li>") mit eingeschlossen.
Hinzu kam noch, dass die Schleife vor der letzten preg_replace-Funktion stand, welche auch einen leeren Listen-Tag am Listenanfang generierte.
Nun habe ich aber den Code entsprechend angepasst und das Problem sollte behoben sein:
PHP:
    while(preg_match("#\[list\].*\[\*\].*\[/list\]#is", $format))
    {
      $format = preg_replace("#\[list\](.*)\[\*\](.*)\[/list\]#is", "
[list]\\1</li><li>\\2
[/list]", $format);
    }

    $format = preg_replace("#\[list\](.+?)\[/list\]#is", "<ul><li>\\1</li></ul>", $format);

    while(preg_match("#<ul>.*<li>\s*</li>.*</ul>#is", $format))
    {
$format = preg_replace("#<ul>(.*)<li>\s*</li>(.*)</ul>#is", "<ul>\\1\\2</ul>", $format);
    }
Nun bleibt nurnoch die zweite Frage offen. ;)
 
Zuletzt bearbeitet:
Zurück
Oben