Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Разрезать текст не по тегу
 
 автор: Wyfinger   (28.11.2009 в 03:03)   письмо автору
 
 

Добрый день уважаемые господа.

Столкнулся с задачей: есть новости, в которых могут встречаться теги простого форматирования (а, b, strong, i и пр.) нужно усеч этот текст для представления на главной странице и добавляется ссылка "читать дальше".
Проблема в том, что если просто делать substr() разрез может попасть на тег вроде:
Это просто пример <stro|ng>жирного<strong> текста

| - предполагаемый разрез

Чтобы этого не случилось, я делаю поиск следующей позиции, где выравнивается баланс открытых и закрытых тегов ("<" и ">") вот как:
// Получение позиции в строке, после символа $l, где закрываются 
// ранее открытые теги, это накладывает условия на форматирование новостей
function correct_length($str, $l) {
    $balance = 0;
    $strlen = strlen($str);
    $result = $strlen;
    for($i=1; $i<=$strlen; $i++) {
        if(substr($str, $i, 1)=='<')  $balance++;
        if(substr($str, $i, 1)=='>')  $balance--;
        if(($i>=$l) && ($balance==0)) {
            $result = $i+1;
            break;
        }
    }
    return $result;
}


Это хорошо работает для не закрываемых тегов, вроде img, но для парных работает неверно:
Это просто пример <strong>|жирного<strong> текста
.

Я пока вижу одно решение - составить список возможных для новостей тегов и морфологически разбирать весь текст считая баланс "<" и ">" и самих тегов "<a>" и "</a>" и т.д.

Но может есть другие варианты.. может кто-то может предложить.

P.S. думал над следующим вариантом: вырезать все теги, узнать на какое слово попал разрез, потом искать это слово в исходном тексте и резать по нему. Но это не всегда будет работать.

  Ответить  
 
 автор: sim5   (28.11.2009 в 05:43)   письмо автору
 
   для: Wyfinger   (28.11.2009 в 03:03)
 

Лучше вообще очистить текст от тегов, затем отрезать необходимое, ведь тег может быть и в начале текста, причем несколько, и вложенных.

  Ответить  
 
 автор: Wyfinger   (28.11.2009 в 08:45)   письмо автору
 
   для: sim5   (28.11.2009 в 05:43)
 

Лучше всего вставлять в новость специальный тег - разделитель краткого и полного представления, тогда все будет здорово, только придется вручную переписать уже имеющиеся новости.

Но это один вариант, предложение с анализом тегов тоже эффективно, тогда можно будет сразу вырезать потенциально опасные теги (хотя зачем?, если все новости пишу я..).

В общем если есть мысли - высказывайтесь.

  Ответить  
 
 автор: sim5   (28.11.2009 в 09:04)   письмо автору
 
   для: Wyfinger   (28.11.2009 в 08:45)
 

<p>абвгд <b>иклмн опрст <i>юфцх.... далее обрезали. Какой смысл в тегах? Коротко от новости, единственный нужный тег, это ссылка на всю новость.

  Ответить  
 
 автор: Wyfinger   (30.11.2009 в 05:04)   письмо автору
 
   для: sim5   (28.11.2009 в 09:04)
 

Это мне понравилось, буду в превью новости выводить часть текста без форматирования.

  Ответить  
 
 автор: Николай2357   (28.11.2009 в 11:39)   письмо автору
 
   для: sim5   (28.11.2009 в 05:43)
 

Наверно наоборот лучше... Сначала обрезать, потом очистить. Обрезать и в SQL можно, если по пробелам.

  Ответить  
 
 автор: sim5   (28.11.2009 в 11:56)   письмо автору
 
   для: Николай2357   (28.11.2009 в 11:39)
 

Да собственно без разницы, единственно, что чистить меньше, главное убрать их. Не понимаю к чему они нужны, и ради чего такая заморочка.

  Ответить  
 
 автор: Jackkum   (28.11.2009 в 21:16)   письмо автору
 
   для: Wyfinger   (28.11.2009 в 03:03)
 


<?php

function getTextWithoutHtmlTags$text )
{
    
$reg '<[A-z\/]*>';
    
$text eregi_replace($reg""$text);
    
    return 
$text;
}

$textHtml "<p>простой текст простой текст</p> простой текст простой текст простой текст <strong>простой текст</strong>";
$text     getTextWithoutHtmlTags$textHtml );
$text     trimsubstr($text,0,50) ) . '...';
echo 
$text;
?>

  Ответить  
 
 автор: Николай2357   (28.11.2009 в 22:09)   письмо автору
 
   для: Jackkum   (28.11.2009 в 21:16)
 

А так если?
<?php 

function getTextWithoutHtmlTags$text 

    
$reg '<[A-z\/]*>'
    
$text eregi_replace($reg""$text); 
     
    return 
$text


$textHtml '<p style="color:red">простой текст простой текст</p> простой текст простой текст простой текст <strong>простой текст</strong>'
$text     getTextWithoutHtmlTags$textHtml ); 
$text     trimsubstr($text,0,50) ) . '...'
echo 
$text
?>   

  Ответить  
 
 автор: sim5   (29.11.2009 в 05:47)   письмо автору
 
   для: Николай2357   (28.11.2009 в 22:09)
 

preg_....
А разве strip_tags не справится с этой задачей?

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 08:53)   письмо автору
 
   для: sim5   (29.11.2009 в 05:47)
 

Ну это не мой скрипт, я просто показал, что ничего не выйдет, если в тегах будут стили.
Впрочем strip_tags() действительно не справится с поставленной задачей.

  Ответить  
 
 автор: sim5   (29.11.2009 в 09:14)   письмо автору
 
   для: Николай2357   (29.11.2009 в 08:53)
 

Странно, а у мой strip_tags справляется:
<?
$textHtml 
'<p style="color:red">простой текст простой текст</p> простой текст простой текст простой текст <strong>простой текст</strong>';
echo 
strip_tags($textHtml);

и полученный исходник:
простой текст простой текст простой текст простой текст простой текст простой текст

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 09:17)   письмо автору
 
   для: sim5   (29.11.2009 в 09:14)
 

А если текст такой:

<?
$textHtml 
'<p style="color:red">простой текст простой текст</p>простой текст простой текст простой текст <strong>простой текст</strong>';

  Ответить  
 
 автор: sim5   (29.11.2009 в 09:23)   письмо автору
 
   для: Николай2357   (29.11.2009 в 09:17)
 

А чем второй отличается от первого? Ну получите текстпростой вмето текст простой

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 09:27)   письмо автору
 
   для: sim5   (29.11.2009 в 09:23)
 

Вот именно... А надо оно?

  Ответить  
 
 автор: sim5   (29.11.2009 в 09:29)   письмо автору
 
   для: Николай2357   (29.11.2009 в 09:27)
 

Ну вы извените, если с дури клеить все слова в кучу, то это ваши проблемы, а не разработчиков РНР.
Тем более, что без применения вырезки, это также будет читаться на странице слитно, что говорит о том, что верстальщик идиот, либо малограмотный.

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 09:51)   письмо автору
 
   для: sim5   (29.11.2009 в 09:29)
 

Взгляните пожалуйста на исходник этой страницы...
Вообще все это решается довольно просто:
<?
    
function getTextWithoutHtmlTags($text)
    {
        
$tags = array(  
                        
"\n",
                        
'</p>',
                        
'</P>',                        
                        
'<br>',
                        
'<br />',                        
                        
'<BR>',
                        
'</td>',
                        
'</TD>',
                        
'</div>' ,
                        
'</DIV>' ,                                                      
                      );
                      
        
$n array_fill(0count($tags), ' ');                      
      
        
$text str_replace($tags$n$text);
        return 
nl2br(strip_tags($text));
    }
Это на все случаи жизни, можно верхний регистр и не принимать в расчет. Но многие визивиг-редакторы именно в таком формате и выдают html...
А вы говорите - идиоты.

  Ответить  
 
 автор: sim5   (29.11.2009 в 09:57)   письмо автору
 
   для: Николай2357   (29.11.2009 в 09:51)
 

Вот такое:
текст</
p>простой

может только человек по собственному недосмотру допустить.
У меня всегда были проблемы с орфографией, и я привык проводить работу над ошибками, если отдаю кому либо документ. Пенять на редактор, это значит наплевать на свою работу. )

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 10:07)   письмо автору
 
   для: sim5   (29.11.2009 в 09:57)
 

А причем тут разрыв тега? Новости часто (очень часто) добавляются через админ-панель. А в админ-панели часто (очень часто) используются визивиг-редакторы. А они часто (очень часто) не ставят пробелов или прерносов строк после тегов <p></p> <br> <div></div> и так далее. Так что работу над ошибками должен делать скрипт. А strip_tags() в чистом виде не справится. Вот и.

  Ответить  
 
 автор: sim5   (29.11.2009 в 10:18)   письмо автору
 
   для: Николай2357   (29.11.2009 в 10:07)
 

Если вам охота проводить работу над чужими ошибками, пожалуйста, я ничего не имею против. ;-)
Я бы такой редактор просто выкинул бы в помойку, нафик мне нужны лишние проблемы. Либо, если уже мне так надо, исправил бы редактор так, что бы он вставлял теги по человечески. Знаете, проблему можно найти даже на ровном месте, а если подстраиваться под редакторы, которые мягко сказать некорректные, то вы не страницы будет отдавать пользователю, а заниматься разборами каждой мелочи, в то время когда более важная работа требуется.

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 10:28)   письмо автору
 
   для: sim5   (29.11.2009 в 10:18)
 

Зря Вы так... Практически все визивиг редакторы, которые основаны на JS выдают такой результат. В остальном они чудесно справляются со своими обязанностями. И я не думаю, что это некорректные редакторы, просто это особенности технологии.
Исправлять такой редактор нет никакого смысла, и тем более это ни как не сократит время, что бы заняться более важной работой. Писать свой, используя другой подход... То да конечно. Но вряд ли копикстартер станет это делать.
А проблема решается несколькими строчками...
Впрочем я тоже ничего не имею против, у каждого свой подход :) Мне это тоже не очень то по душе.

  Ответить  
 
 автор: sim5   (29.11.2009 в 10:34)   письмо автору
 
   для: Николай2357   (29.11.2009 в 10:28)
 

Я не привык пенять на редакторы, и не пользуюсь в написании визуальными редакторами. И если редатор у меня будет косячить, то я его просто исправлю или выкину. А допускать ошибки на странице, надеяь на то, что пользователи поймут, что это не я балбес, а такой редактор, это ну я даже и не знаю слов, коими бы это можно было назвать.
Я вам не даю обязательных рекомендаций, поступайте как хотите. Считаете что и так сойдет, ссылаясь на огрехи редактора, да заради бога ;-)

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 10:46)   письмо автору
 
   для: sim5   (29.11.2009 в 10:34)
 

Да почему же это огрехи то... Иногда специально, что бы уменьшить вес html код пишется в одну строку. Какие же это огрехи? Какие же это ошибки?
Не согласный я. :)

  Ответить  
 
 автор: sim5   (29.11.2009 в 10:48)   письмо автору
 
   для: Николай2357   (29.11.2009 в 10:46)
 

Если вы напишите код в одну строку, наплевав на проблеы, то это что? Это ваш баг или редактора?

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 10:59)   письмо автору
 
   для: sim5   (29.11.2009 в 10:48)
 

Пробелы как раз и не нужны в таких тегах как <br>, <p> и особенно <div>. Даже вредно бывает. Переносы - да, для читабельности. Но не пробелы. Не хочу я на них плевать, я их ставить не всегда то хочу. Особенно в вап версиях.

  Ответить  
 
 автор: sim5   (29.11.2009 в 11:02)   письмо автору
 
   для: Николай2357   (29.11.2009 в 10:59)
 

Что вы говорите?! Даже и не знал, что "разорванный" тег брвузер примет за проблел. Акститесь, Николай :)
Эффективным лечением может быть только одно лечение, когда лечится не следствие, а причина. Мне больше добавить нечего.

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 11:34)   письмо автору
 
   для: sim5   (29.11.2009 в 11:02)
 

Ну что Вы такое говорите... Какой разорванный тег? Или Вы назовете этод код невалидным?
<p style="color:red">простой текст простой текст</p>простой текст<div>простой текст</div>простой текст <strong>простой текст</strong>

А именно он будет обработан криво strip_tags() в чистом виде, применительно к данной задаче. И это не следствие никакое. И даже не болезнь. И в лечении не нуждается. Это нормальный, валидный код, который нужно подобающим образом обработать и вывести...

  Ответить  
 
 автор: sim5   (29.11.2009 в 12:15)   письмо автору
 
   для: Николай2357   (29.11.2009 в 11:34)
 

А, вы о стыках тега и текста. Валидный, но некчемный )

  Ответить  
 
 автор: Николай2357   (29.11.2009 в 14:40)   письмо автору
 
   для: sim5   (29.11.2009 в 12:15)
 

Ну да, не очень кчемный :) Но факт есть факт - визивиги его именно так и генерят зачастую.

  Ответить  
 
 автор: Jackkum   (29.11.2009 в 11:43)   письмо автору
 
   для: sim5   (29.11.2009 в 11:02)
 

О чем спорите то, способов то много, можно просто подправить рег. выражение добавить в шаблон и другие символы... :)

  Ответить  
 
 автор: mihdan   (30.11.2009 в 16:55)   письмо автору
 
   для: Wyfinger   (28.11.2009 в 03:03)
 

   
<?php
function cutStr($str$lenght 100) {
        
$str strip_tags($str);
        if (
strlen($str) >= $lenght) {
            
$wrap wordwrap($str$lenght"~");
            
$str_cut substr($wrap0strpos($wrap"~"));
            
$str_cut .= ' ...';
            return 
$str_cut;
        } else {
            
$str_cut $str ' ...';
            return 
$str_cut;
        }
}
?>

  Ответить  
 
 автор: mihdan   (02.12.2009 в 16:26)   письмо автору
 
   для: mihdan   (30.11.2009 в 16:55)
 

Чтобы не обрезать теги

<?php
function breakword ($txt,$len,$delim='\s;,.!?:#') {
    
$txt preg_replace_callback ("#(</?[a-z]+(?:>|\s[^>]*>)|[^<]+)#mi"
                                  
,create_function('$a'
                                                  
,'static $len = '.$len.';'
                                                  
.'$len1 = $len-1;'
                                                  
.'$delim = \''.str_replace("#","\\#",$delim).'\';'
                                                  
.'if ("<" == $a[0]{0}) return $a[0];'
                                                  
.'if ($len<=0) return "";'
                                                  
.'$res = preg_split("#(.{0,$len1}+(?=[$delim]))|(.{0,$len}[^$delim]*)#ms",$a[0],2,PREG_SPLIT_DELIM_CAPTURE);'
                                                  
.'if ($res[1]) { $len -= strlen($res[1])+1; $res = $res[1];}'
                                                  
.'else         { $len -= strlen($res[2]); $res = $res[2];}'
                                                  
.'$res = rtrim($res);/*preg_replace("#[$delim]+$#m","",$res);*/'
                                                  
.'return $res;')
                                  ,
$txt);
     while (
preg_match("#<([a-z]+)[^>]*>\s*</\\1>#mi",$txt)) {
         
$txt preg_replace("#<([a-z]+)[^>]*>\s*</\\1>#mi","",$txt);
     }
     return 
$txt;
}
?>

  Ответить  
 
 автор: Trianon   (02.12.2009 в 16:36)   письмо автору
 
   для: mihdan   (02.12.2009 в 16:26)
 

А вот это обязательно надо было - текст хелпер-функции в строковый литерал совать?
Его ж не прочтешь нормально!
Вот зачем этот выпендреж на ровном месте?

  Ответить  
 
 автор: Fractured#   (02.12.2009 в 17:28)   письмо автору
 
   для: Trianon   (02.12.2009 в 16:36)
 

Ему статус не позволяет писать проще

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования