Как правильно обрезать строку с HTML тегами. Есть ли готовые решения?

  • Автор темы Автор темы xintrea
  • Дата начала Дата начала

xintrea

Новичок
Как правильно обрезать строку с HTML тегами. Есть ли готовые решения?

Здравствуйте!

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

- В строке могут попадаться HTML теги, и их символы при подсчете учитывать ненадо.
- Нельзя допускать, чтобы строка заканчивалась в середине текста тега, т.е. нельзя чтобы конец был типа "...ля<text colo"
- Все теги, открытые в строке, должны быть закрыты, пусть даже это увеличит итоговую строку
- Ну и желательно чтобы строка не оканчивалась на середине слова, а хотя бы была обрезана до ближайшего пробела (разделителя).

В общем, нужна функция, которая красиво обрезает строки, в которых встречается HTML код.

Вопрос - есть ли в природе уже готовые функции, которые умеют так делать? Может, завалялись у кого в загажниках?

На этом форуме нашел только такую тему
http://phpclub.ru/talk/showthread.php?s=&threadid=33914&highlight=%EE%E1%F0%E5%E7%E0%F2%FC+%F1%F2%F0%EE%EA%F3
но в ней ничего путного товарищу не предложили. Сообщения в ней за 2003 год, а щас 2006, может за это время появились хорошие готовые решения?

Заранее спасибо за помощь.
 
Разбить на несколько этапов:
1,2,3)Обрезать html теги, если грубо - strip_tags или изящно preg_replace в мануале есть пример, неплохой.

4) Usage: string wordwrap (string str [, int width [, string break [, int cut]]])
 
Этот метотд испортит HTML форматирование, точнее вовсе его уберет.

А нужно чтобы HTML форматирование осталось, т. е. если в строке есть HTML-теги, их нужно оставить.

Ну например, если в первых 200 символах был тег <A HREF=...>ссылка</A>, нужно чтобы эта ссылка была видна как ссылка, а не просто как текст. То же касается и всех других тегов форматирования внешнего вида текста.
 
Предполагаю, можно сделать следующим образом:
1) Разбиваем строку в массив по тегам, через explode с "<".
2) С полученного массива рабиваем каждый элемент массива через explode с ">". Всё собирается в 1 массив.
3) Находим в массивы элементы, которые не имеют "<" и ">".
4) Находим их длину и находим последний нужный элемент.
5) Собираем массив через implode. (Тут ещё остаётся дозакрыть тэги для последнего нужного элемента).
 
На правах безумной идеи для несложных строк:
PHP:
preg_match('~^(?>(?><[^>]*>\s*)*[^<]){0,200}(?=\s)~s', $text, $m);
echo tidy_repair_string($m[0]);
 
Автор оригинала: SelenIT
На правах безумной идеи для несложных строк:
PHP:
preg_match('~^(?>(?><[^>]*>\s*)*[^<]){0,200}(?=\s)~s', $text, $m);
echo tidy_repair_string($m[0]);
Туго у меня с англицким, я что-то на php.net не понял что делает функция tidy_repair_string() ? В рунете тоже перевода нигде нет.

Есть подозрения, что она "выправляет" HTML код, проверяя правильность открытия-закрытия тегов? Во всяком случае в примере

http://ru.php.net/manual/ru/function.tidy-repair-string.php

идет исправление </i> на </p>

Было
...
<body>
<p>error</i>
</body>
...

Стало
...
<body>
<p>error</p>
</body>
...

Или у них там просто опечатка?

В любом случае, использовать Tidy библиотеку мне нельзя - проект должен работать на ранних версиях PHP4, а тут ограничение - Tidy 1.0 is just for PHP 4.3.x, while Tidy 2.0 is just for PHP 5.

Я не совсем понял, может использовать tidy_repair_string() не обязательно?
 
Это был вариант готового решения для автозакрытия оставшихся открытыми при обрезке тегов - Tidy как раз отвечает за корректное соответствие закрывающих тегов открывающим (в примере не опечатка). Конечно, в любом случае нужна "доработка напильником" (в частности, у Tidy ограничен набор поддерживаемых кодировок), но это могло бы избавить от рутинного разбора стека незакрытых тегов.
 
опять же "на правах безумной идеи" (с)
вырезать все теги, найти последнее слово, в исходной строке найти это же слово
 
Путь решения мне видется таким:
- Вырезаете теги, складываете их в массив.
- Вырезанные из тегов слова складываете во второй массив
- В полученном "голом" тексте отрезаете 200 символов (регулярные выражения).
- Вставляете теги обратно в отрезанный текст.

Когда мне необходимо было убирать лишние пробелы в исходном коде страницы везде, кроме <script></script>
я юзал код, позаимствованный из, если правильно помню, Smarty .

Могу вечером показать своё решение. Думаю может помочь.
 
Если с одиночными тегами проблема решаема - то если у тебя в html-тексте есть таблицы - проблему решить будет крайне сложно...
Если нет таблиц, то ИМХО, лучше пробежаться по первым 200 символам и если нашел открывающийся тег - бежать дальше и искать закрывающийся. Как только находишь последний закрывающийся тег и количество найденных символов превышает 200 - ищешь первый пробельный символ и завершаешь цикл.

Сам на эту тему не заморачиваюсь, ибо не было важной необходимости и использую strip_tags
 
берешь первый встреченный тег. строка не будет короче его парного тега. и т.д.
 
PHP:
function clean_space($source)
{
preg_match_all("!<script[^>]+>.*?</script>!is", $source, $match);
preg_match_all("!<textarea[^>]+>.*?</textarea>!is", $source, $match_text);
$_script_blocks = $match[0];
$_textarea_blocks=$match_text[0];
$source = preg_replace("!<script[^>]+>.*?</script>!is", '####Vadim_S_replace####', $source);
$source = preg_replace("!<textarea[^>]+>.*?</textarea>!is", '####Vadim_S_replace_text####', $source);
$pattern = array("\n", "\r");
$replace = array('','');
$source = str_replace ($pattern, $replace, $source);

// remove all leading spaces, tabs and carriage returns NOT
// preceeded by a php close tag.

// replace script blocks
foreach($_script_blocks as $curr_block) {
$source = preg_replace("!####Vadim_S_replace####!",$curr_block,$source,1);

}
foreach($_textarea_blocks as $curr_block) {
$source = preg_replace("!####Vadim_S_replace_text####!",$curr_block,$source,1);

}
$pattern = array("\r\n//", "\n//", "\r//");
$replace= array(' //', ' //', ' //');
$source = str_replace ($pattern, $replace, $source);


return $source;
}

script, textarea заменить на то, чтоб все теги вырезались....
Хотя наверное не самый изящный вариант я думаю получится
 
Vadim S., сколько будет работать твой скрипт, если html-текс будет достаточно большим??? Не, это не эффективный выход из ситуевины...
 
Nogrogomed, вытащить из файла только первые допустим (20 Кб) Вам религия не позволяет ?

Ваш подход ничем принципиально не отличается. Те же регулярки, только вид сбоку.

Скрипт готовый. Можете запустить и проверить сколько он будет работать на больших объёмах. Тексты в 300-400 Кб отрабатывает на раз.
Довольно редко встречаются html файлы большего объёма.



Ежели у Вас 10 Мб файл, то при каждом его открытии отрезать от него 200 символов будет только ненормальный. Это должно делаться только один раз (при первом открытии). А дальше делается контроль за изменением этого текста и т.д.
 
Сверху