Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Przycinanie tekstu z formatowaniem HTML
Forum PHP.pl > Forum > PHP
Diabl0
Witam

Jak w temacie głowię się nad problemem przycinania tekstu z formatowaniem HTML (tekst z edytorów typu TinyMCE) do określonej ilości znaków z zachowaniem formatowania, i na razie nic sensownego nie wpada mi do głowy (a i google nic nie podpowiada ciekawego).

Problem jest taki: mam jakiś dłuższy tekst z formatowaniem HTML. Dla uproszczenia i przykładu:

ala ma kota
  1. <b>al<i>a</i> <u>ma</u></b> <i>ko<b>ta</b></i>


I potrzebuję na stronie wyświetlić przykładowo 6 znaków z tego tekstu z zachowaniem formatowania czyli:

ala ma
  1. <b>al<i>a</i> <u>ma</u></b>


Ma ktoś jakiś pomysł jak do tego podejść, albo może mnie nakierować na odpowiednią klasę/przykład ?
Diabl0
Ok... Tidy już teraz używam do domknięcia brakujących tagów ale nadal nie wiem jak skrócić ciąg do zadanej długości według widocznych znaków. Zwykłe substr nie zwraca uwagi czy to jest tag czy nie i tnie jak leci. Kombinowałem trochę z substr i strip_tags ale to też raczej błędna droga... Jedyne co mi przychodzi do głowy to żmudna ręczna analiza stringa od początku aż do trafienia w odpowiedni "czysty" znak ale to jest od cholery obliczeń (i raczej sporo kodu).

Dlatego pytam się czy już ktoś tego nie robił tudzież gdzieś widział gotowe rozwiązanie aby nie wymyślać po raz kolejny koła...
NuLL
Zgodne z XHTML - wymaga tagow typu <br/>

  1. <?php
  2. function html_substr(
  3. $posttext, #tekst do skrocenia
  4. $minimum_length = 200, #minimalna dlugosc
  5. $length_offset = 20, #dlugosc offsetu
  6. $cut_words = FALSE, #ciac slowa ?
  7. $dots = TRUE #dokleic 3 kropki questionmark.gif
  8. ) {
  9.  
  10.    $tag_counter = 0;
  11.    $quotes_on = FALSE;
  12.  
  13.    if (strlen($posttext) > $minimum_length) {
  14.  
  15.        $c = 0;
  16.        for ($i = 0; $i < strlen($posttext); $i++) {
  17.  
  18.            $current_char = substr($posttext,$i,1);
  19.            if ($i < strlen($posttext) - 1) {
  20.                $next_char = substr($posttext,$i + 1,1);
  21.            }
  22.            else {
  23.                $next_char = "";
  24.            }
  25.  
  26.            if (!$quotes_on) {
  27.                if ($current_char == '<') {
  28.                    if ($next_char == '/') {
  29.                        $tag_counter += 1;
  30.                    }
  31.                    else {
  32.                        $tag_counter += 3;
  33.                    }
  34.                }
  35.  
  36.                if ($current_char == '/' && $tag_counter <> 0) $tag_counter -= 2;
  37.   
  38.                if ($current_char == '>') $tag_counter -= 1;
  39.  
  40.                if ($current_char == '"') $quotes_on = TRUE;
  41.            }
  42.            else {
  43.                if ($current_char == '"') $quotes_on = FALSE;
  44.            }
  45.            
  46.            if($tag_counter == 2 || $tag_counter == 0){
  47.                $c++;
  48.            }          
  49.                            
  50.            if ($c > $minimum_length - $length_offset && $tag_counter == 0 && ($next_char == ' ' || $cut_words == TRUE)) {
  51.                $posttext = substr($posttext,0,$i + 1);              
  52.                if($dots){
  53.                    $posttext .= '...';
  54.                }
  55.                return $posttext;
  56.            }
  57.        }
  58.    }  
  59.    return $posttext;
  60. }
  61. ?>
Diabl0
Dzięki... Nie jest to ideał (np. wymóg XHTML) ale za to podsunał mi własny pomysł którego szybka implementacja znajduje się poniżej:

  1. <?php
  2.  
  3. /**
  4.  * Diablos HTML truncate
  5.  *
  6.  * My version of choping strings (with html tags) around a specified length.
  7.  *
  8.  * @author Diabl0
  9.  * @version 0.5
  10.  * @uses Tidy Functions
  11.  *
  12.  * @param string $text
  13.  * @param integer $minimum_length
  14.  * @param integer $length_offset
  15.  * @param boolean $word_cut
  16.  * @param string $postfix
  17.  * @return string
  18.  */
  19. function my_html_substr($text, $minimum_length = '256', $length_offset = '20', $word_cut = false, $postfix = '...') {
  20. $tag_counter = 0;
  21. $quotes_on = FALSE;
  22.  
  23. // $text = html_entity_decode($text);
  24. $text = preg_replace('/\s+/', ' ', $text);
  25.  
  26. if (strlen(strip_tags($text)) > $minimum_length) {
  27.  
  28. $st = 0;
  29. for ($i = 0; $i < strlen($text); $i++) {
  30. $current_char = substr($text,$i,1);
  31. if ($current_char == '<') {
  32. // Mamy początek znacznika - zakończenia znacznika
  33. $jump = strpos($text, '>', $i);
  34. $i = $jump;
  35. } else {
  36. // Mamy czysty znak, liczymy go i jedziemy dalej.
  37. $st++;
  38. }
  39.  
  40.  
  41. // Mamy cały string?
  42. if ($st == $minimum_length) {
  43. if ($word_cut != True) {
  44. // Nie możemy ciąć słów :( więc trzeba znależć spację lub enter
  45. $space = strpos($text, ' ', $i);
  46. $enter = strpos($text, "\n", $i);
  47. if ( ($space < $enter OR !$enter) AND $space < strlen($text) AND $space < $minimum_length+$length_offset) {
  48. $output = $output = substr($text, 0, $space);
  49. } elseif ( ($space > $enter OR !$space) AND $enter < strlen($text) AND $enter < $minimum_length+$length_offset) {
  50. $output = $output = substr($text, 0, $enter);
  51. } else {
  52. $output = $text;
  53. }
  54. } else {
  55. // Możemy ciąć więc tniemy jak leci
  56. $output = substr($text, 0, $i);
  57. }
  58.  
  59. $output .= $postfix;
  60. // Mamy nasz upragniony string, czas go poprawić pod kątem zamkniętych znaczników
  61. if( function_exists( 'tidy_parse_string' ) ) {
  62. $tidy_config = array( 'indent' => TRUE, 'wrap' => 0 );
  63. $html = $output;
  64. $html = tidy_repair_string($html, $tidy_config, 'raw');
  65. $html = substr($html, strpos($html, '<body>')+6);
  66. $html = trim(substr($html, 0, strpos($html, '</body>')));
  67. $output = $html;
  68. }
  69.  
  70.  
  71. return $output;
  72. }
  73.  
  74. }
  75. }
  76. return $text;
  77. }
  78.  
  79. ?>


Nie jest on idealny (wymaga Tidy), dokładnie sprawdzony (nie jestem pewien wszystkich warunków), ani nawet ładny (jeszcze nad nim myślę), czy porządnie skomentowany (powstawał na szybko). Ale wrzucam go tutaj do skomentowania (i być może podsunięcia innych ciekawych rozwiązań).
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.