Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: preg_replace: Zagnieżdżone listy nie są interpretowane.
Forum PHP.pl > Forum > PHP
Asmox
Fragment kodu odpowiedzialnego za parsowanie bbcode wygląda tak:
  1. $text = preg_replace("#\[ul\](.*)\[/ul\]#simx", "<ul>\\1</ul>", $text);
  2. $text = preg_replace("#\[ol\](.*)\[/ol\]#simx", "<ol>\\1</ol>", $text);
  3. $text = preg_replace('#\[li\](.*?)\[/li\]#si', '<li>\\1</li>', $text); // [li]abc[/li]
  4. $text = preg_replace('#\[\*\](.*?)\n#si', '<li>\\1</li>', $text); // [*]abc


Niestety nie działa mi zagnieżdżanie list w takim przypadku. Gdy mam np.
Kod
[ol]
[li]el. 1
  [ol]
    [li]el1.1[/li]
    [li]el1.2[/li]
  [/ol]
  [li]el2[/li]
[/ol]

To wewnętrzny [ol] jest zupełnie ignorowany, a punkty el1.1 i el1.2 są traktowane jako elementy listy nadrzędnej. Mam wrażenie że to może być coś nie tak z kolejnością parsowania, ale gdy zamieniłem funkcje od list z funkcjami od punktów to nic się nie zmieniło. Bardzo proszę o pomoc.
Sinevar
Coś mi się wydaje, że to będzie więcej zabawy z:
- http://www.php.net/manual/en/regexp.refere...nal-options.php
- http://www.php.net/manual/en/regexp.reference.recursive.php
Asmox
Chyba na moim obecnym poziomie to zagadnienie mnie trochę przerasta, czy mógłbym zatem prosić o najprostszego gotowca? Jeżeli takowy prosty nie istnieje to po prostu zrobię zamienianie [ol] na <ol> i [/ol] na </ol> i będzie po sprawie.
Sinevar
Pozwoliłem sobie napisać funkcję, która znajduje elementy [ol], [li] rekursywnie.

Do testowania używam takiego zbioru danych:

  1. $text = '
  2. [ol]
  3. [li]el. 1
  4. [ol]
  5. [li]el1.1[/li]
  6. [li]el1.2
  7. [ol]
  8. [li]efssdf[/li]
  9. [/ol]
  10. [/li]
  11. [/ol]
  12. [/li]
  13. [li]el2[/li]
  14. [/ol]
  15. [ol]
  16. [li]DEDFDFFD
  17. [ol]
  18. [li]AAA[/li]
  19. [/ol]
  20. [/li]
  21. [li]fdsfs[/li]
  22. [/ol]
  23. [ol]
  24. [li]11113442ADEDFDFFD
  25. [ol]
  26. [li]fdfsd
  27. [ol]
  28. [li]ela1[/li]
  29. [li]ela
  30. [ol]
  31. [li]ola
  32. [ol]
  33. [li]fsdfsdfsd[/li]
  34. [/ol]
  35. [/li]
  36. [/ol]
  37. [/li]
  38. [/li]
  39. [/ol]
  40. [/li]
  41. [/ol]
  42. [ol]
  43. [li]fddf
  44. EEfds
  45. [/li]
  46. [/ol]
  47. [ol]
  48. [li]fddf EEfds45453545435[/li]
  49. [li]fddf EEfds45453545435[/li]
  50. [li]fddf EEfds45453545435[/li]
  51. [li]fddf EEfds45453545435[/li]
  52. [/ol]
  53. ';


A funkcja to:

  1. function recursiveRegexp($text, $level, $tag = 'ol')
  2. {
  3. static $max0Levels = null;
  4.  
  5. $pattern = "#\[$tag\](((?:[^[]|\[(?!/?$tag\])|(?R)))*)\[/$tag\]#";
  6. preg_match_all($pattern, $text, $matches);
  7.  
  8. $count = count($matches);
  9. if (null === $max0Levels)
  10. {
  11. $count = @count($matches[1]) ?: 0;
  12. $max0Levels = $count;
  13. }
  14.  
  15. if (1 < $count)
  16. {
  17. for ($i = 0 ; $i < $count ; $i++)
  18. {
  19. if (is_string($matches[1][$i]) && 0 < strlen($matches[1][$i]))
  20. {
  21. echo "Level $level: {$matches[1][$i]} <br/>";
  22. recursiveRegexp($matches[1][$i], $level+1, $tag);
  23. }
  24. }
  25. }
  26. }


No i wywołanie to recursiveRegexp($text, 0);, a na wyjściu pojawia się:

Kod
Level 0: [li]el. 1 [ol] [li]el1.1[/li] [li]el1.2 [ol] [li]efssdf[/li] [/ol] [/li] [/ol] [/li] [li]el2[/li]
Level 1: [li]el1.1[/li] [li]el1.2 [ol] [li]efssdf[/li] [/ol] [/li]
Level 2: [li]efssdf[/li]
Level 0: [li]DEDFDFFD [ol] [li]AAA[/li] [/ol] [/li] [li]fdsfs[/li]
Level 1: [li]AAA[/li]
Level 0: [li]fdfsd [ol] [li]ela1[/li] [li]ela [ol] [li]ola [ol] [li]fsdfsdfsd[/li] [/ol] [/li] [/ol] [/li] [/li] [/ol] [/li]
Level 1: [li]ela1[/li] [li]ela [ol] [li]ola [ol] [li]fsdfsdfsd[/li] [/ol] [/li] [/ol] [/li] [/li]
Level 2: [li]ola [ol] [li]fsdfsdfsd[/li] [/ol] [/li]
Level 3: [li]fsdfsdfsd[/li]
Level 0: [li]fddf EEfds [/li]
Level 0: [li]fddf EEfds45453545435[/li] [li]fddf EEfds45453545435[/li] [li]fddf EEfds45453545435[/li] [li]fddf EEfds45453545435[/li]


Jest tylko jedno małe ale...po co to wszystko, skoro możnaby było po prostu zastosować coś na wzór:
  1. $new = str_replace(array('[li]', '[ol]', '[/li]', '[/ol]'), array('<li>', '<ol>', '</li>', '</ol>'), $text);

Tak czy inaczej, może to rekurencyjne monstrum, które skleciłem, komuś się przyda smile.gif
Asmox
Cytat(Sinevar @ 30.04.2012, 10:16:36 ) *
Jest tylko jedno małe ale...po co to wszystko, skoro możnaby było po prostu zastosować coś na wzór:
  1. $new = str_replace(array('[li]', '[ol]', '[/li]', '[/ol]'), array('<li>', '<ol>', '</li>', '</ol>'), $text);

Pisząc swoją stronę, używam tagów BB bo nawiasy ostrokątne czasem mi się przydają :-) . Zwykła zamiana [{ewentualny_ukośnik}{nazwa_taga}] na <{ewentualny_ukośnik}{nazwa_taga}> bardzo ułatwi mi robotę. Natomiast np. na forum takie rozwiązanie jest raczej niedopuszczalne, bo jak ktoś zapomni zamknąć tag od pogrubienia to wszystko pod spodem będzie pogrubione itd. Tak czy siak, dzięki za pomoc.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.