BBCode und Listen

hpvw

Erfahrenes Mitglied
Welche regulären Ausdrücke muss ich verwenden, um aus:
[ list ]
[ * ]BlaBla
[ * ]BlaBlub
[ / list]
(natürlich ohne Leerzeichen)
< ul >
[ li ]BlaBla
[ li ]BlaBlub
< / ul >

und aus
[ list ]
[ # ]BlaBla
[ # ]BlaBlub
[ / list]
(natürlich auch ohne Leerzeichen)
< ol >
[ li ]BlaBla
[ li ]BlaBlub
< / ol >

zu machen. Gerne auch mit schließendem < / li >
Probiere schon seit 3Std. und komme nicht auf ein gescheites Ergebnis.
Danke für die Antwort hpvw
 
Wie sieht denn dein bisheriges Ergebnis in PHP aus? Code?

PHP:
// Check for List text
$Text = preg_replace("(\[list=point\](.+?)\[\/list\])is",'<ul>$1</ul>',$Text);
$Text = preg_replace("(\[list=num\](.+?)\[\/list\])is",'<ol>$1</ol>',$Text);
$Text = preg_replace("(\[\*\](.+?)\\n)is",'<li>$1</li>',$Text);

Ich glaub das mit den 3h nicht.
 
@_vodoo
So, wie Du schreibst, würde meine Notlösung aussehen.
Ich hätte es halt gerne, dass die Art der Liste durch das fürs < li > stehende BBCode Tag entschieden wird.
Ich hatte mir überlegt, dass ich nach [ list ] irgendwas [ * ] irgendwas [ / list ] und [ list ] irgendwas [ # ] irgendwas [ / list ] suche. Und anschliessend die < li > zusammenbaue.
Als Newbie in Sachen preg_replace ist das aber 'ne fiese Aufgabe.
Mein aktueller Versuch, erstmal nur für unnummerierte Listen (der nicht klappt), sieht so aus:
PHP:
$result = preg_replace("!\[list\]((.|\n)*?)(\[\*\])((.|\n)*)\[/list\]!", "<ul>\\1\\2\\3</ul>", $result);

$result = preg_replace("!\[\*\]((.|\n)*?)!", "<li>\\1", $result);

Viele andere Versuche gingen auch schief.

@Nils
Danke für den Link, leider steht da auch nichts zu nummerierten Listen.
Ich habe schon gesucht, wie verrückt (hier im Forum, in Google) und habe leider nichts passendes gefunden, sonst würde ich keinen Thread eröffnen.

Gruß hpvw
 
Mit der Funktion preg_replace_callback habe ich es in wenigen Minuten gelöst:
PHP:
function parseList($matches)
{
	if(preg_match("/\[#\]/",$matches[1]))
	{
		return "<ol>".str_replace("[#]","<li>",$matches[1])."</ol>";
	}
	else
	{
		return "<ul>".str_replace("[*]","<li>",$matches[1])."</ul>";
	}
}

$result = preg_replace_callback("/\[list\](.*)\[\/list\]/siU", "parseList", $result);
Diese Lösung kann noch ins beliebige verbessert werden, z.B. Liste ganz rausnehmen, falls gar kein oder [#] reingeschrieben wurde oder sowohl als auch [#] in einer einzigen Liste behandeln usw. Die Grenzen sind unendlich, man braucht nur die Funktion "parseList" entsprechend erweitern.
Kurz eine Besprechung der Funktion preg_replace_callback: als zweiter Parameter steht die Funktion, an die die gefundenen Gruppen übergeben werden sollen. Diese Funktion, in unserem Falle "parseList", muss ein Argument übernehmen. Dies wird automatisch als Array gebildet, so wird, im ersten Array-Element ($matches[0]) der Gesamtausdruck abgelegt, im zweiten Element ($matches[1]) die erste Gruppe des regulären Ausdrucks usw. Die Funktion muss mit return einen String zurückgeben: er wird an die Stelle des Patterns gesetzt. Der Rest sollte sich von selbst erklären.

Wenn du das ganze in einer Klasse abhandelst, schreibst du:
PHP:
$result = preg_replace_callback("/\[list\](.*)\[\/list\]/siU", array(&$this,"parseList"), $result);
Das zweite Argument muss dann ein zweielem. Array sein, das zum einen eine Referenz auf die aktuelle Klasse (oder eine andere) übergibt, zum anderen wieder den Namen der Funktion.

Eine Alternative wäre noch die Verwendung der Funktion preg_replace mit dem Pattern-Modifier e (steht für evaluate). Dabei wird die Zeichenkette, die als Ersatz eingefügt wird, wie PHP-Code behandelt, und somit sind auch da Funktionsaufrufe möglich (beachte aber die korrekte Verwendung der Hochkommata!).
 
Vielen Dank Chrstph,
das ist ja der Wahnsinn, die Möglichkeiten scheinen ja echt unendlich.
Eine Frage hätte ich noch:
Gibt es einen Modifier, so dass der Pattern von hinten gesucht wird?
So könnte man (hoffe ich) auch verschachtelte Aufzählungen zulassen.
Alternativ auch einen Modifier, dass er von innen nach außen beginnt?

Nochmal Danke, das hat mich viele Stunden nach vorn gebracht und gibt auch Ideen für andere noch ungelöste Probleme.

Gruß hpvw
 
Habe das Verschachteln jetzt etwas dreckig wie folgt gelöst:
PHP:
        $r = "";
        while ($r != $result) {
            $r = $result;
            $result = preg_replace_callback("/\[list\]((?!(.*\[list\]))(.*))\[\/list\]/siU", "parseList", $result);
        }
 
Zurück