Модераторы: Aliance, skyboy, MoLeX, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как обрезать строку с форматированием 
:(
    Опции темы
Gold Dragon
Дата 17.4.2010, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



Собственно вопрос...

Допустим существует стока с форматирование типа
Код

<h3>Уважаемые посетители, на наших страницах в апреле ... </h3>
<p align="justify">
<span style="color: #000000">&laquo;Профессиональные ОПРОСНИКИ&raquo;</span>, кого-то они направят в выборе профессии, кому-то <b>они</b> помогут оценить возможность перемен для себя!
</p>

Мне нужно обрезать строку и оставить допустим 150 символов. Как это можно сделать сохранив форматирование?

Добавлено через 2 минуты и 49 секунд
как-то странно создалась тема :( попробую продублировать


Собственно вопрос...

Допустим существует стока с форматирование типа
Код

<h3>Уважаемые посетители, на наших страницах в апреле ... </h3>
<p align="justify">
<span style="color: #000000">&laquo;Профессиональные ОПРОСНИКИ&raquo;</span>, кого-то они направят в выборе профессии, кому-то <b>они</b> помогут оценить возможность перемен для себя!
</p>


Мне нужно обрезать строку и оставить допустим 150 символов. Как это можно сделать сохранив форматирование? 


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
Photon
Дата 17.4.2010, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Злобный программер
**


Профиль
Группа: Участник
Сообщений: 282
Регистрация: 27.2.2009
Где: Таганрог

Репутация: нет
Всего: 12



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


--------------------
With best regards..
PM MAIL ICQ Skype GTalk Jabber   Вверх
smartov
Дата 17.4.2010, 20:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


свой собственный
****


Профиль
Группа: Экс. модератор
Сообщений: 4225
Регистрация: 2.2.2006
Где: NJ

Репутация: 4
Всего: 259



Рекурсивная функция, которая вырезает 150 символов, смотрит нету ли в них тегов, отрезает от изначальной строки  и прибавляет к конечной еще кусок длиной в "длина тегов". И так пока текст кроме тегов не станет 150 символов.
После чего надо пробежаться и закрыть все теги.
PM MAIL   Вверх
Gold Dragon
Дата 18.4.2010, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



а примерчик можно, а то что-то не въеду smile не очень я со всякими регулярками


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
ArchNix
Дата 18.4.2010, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 18.4.2010

Репутация: нет
Всего: 1



Примерчик  smile 
Код

$TEST =<<<HTML
<h3>Уважаемые посетители, на наших страницах в апреле ... </h3>
<p align="justify">
<span style="color: #000000">&laquo;Профессиональные ОПРОСНИКИ&raquo;</span>, кого-то они направят в выборе профессии, кому-то <b>они</b> помогут оценить возможность перемен для себя!
</p>
HTML;

$charset = "UTF-8";

mb_regex_encoding($charset);
mb_ereg_search_init($TEST, "([А-я]*)");

$r = mb_ereg_search_getregs();
do {
  $r = mb_ereg_search_regs();
  $arr[] = $r[1];
} while($r);

print_r($arr);

PM MAIL   Вверх
brother79
Дата 19.4.2010, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



1) Тупо отсчитываешь 150 символов, пропуская встретивиеся теги.
2) Если последний тег не закрытый, то 2 вар-та есть, либо закрыть самому, либо обрезать весь


--------------------
PM MAIL WWW   Вверх
Gold Dragon
Дата 19.4.2010, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



ArchNix, попробую что за код... smile


brother79, это не выход. Может быть куча вложенных тегов которые не закроются. И тогда весь сайт поплывёт


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
brother79
Дата 20.4.2010, 05:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Цитата(Gold Dragon @  19.4.2010,  17:13 Найти цитируемый пост)
brother79, это не выход. Может быть куча вложенных тегов которые не закроются. И тогда весь сайт поплывёт 


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

1) пиши полноценный парсер
2) сделай что-то типа 

Код

if (preg_match_all('/([^\<]*)(\<[^\>]+\>)/', $s, $m)) {
  print_r($m)
}


Далее в $m уже будут выделены отдельно все теги и текст между ними, останется только пройтись по этому массиву, считая символы и запоминая какие теги открываются и закрываются, скажем добавляя их в другой массив и удаляя из него при закрытии, а в конце, те, что не удалённые  - закрыть и удалить из массива.

Тут правда конец строки не учитывается, надо или регулярку усложнять или на всякий случай в конце добавить фиктивный тег перед разбором

Это сообщение отредактировал(а) brother79 - 20.4.2010, 05:09


--------------------
PM MAIL WWW   Вверх
Gold Dragon
Дата 20.4.2010, 08:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



в общем начал колдовать.. Но столкнулся с ещё одной бедой.. А если есть таблица? Тут не только нужно считать теги но и структуру считать.. В общем ужас smile


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
SickFxck
Дата 20.4.2010, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Gold Dragon, какая разница — таблица у тебя или что-то другое? Какой ты алгоритм сам для себя выбрал?
PM MAIL   Вверх
Gold Dragon
Дата 20.4.2010, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



разница есть, например, если используются colspan или rowspan. Или что-то типа <col> у которого нет </col>


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
smartov
Дата 20.4.2010, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


свой собственный
****


Профиль
Группа: Экс. модератор
Сообщений: 4225
Регистрация: 2.2.2006
Где: NJ

Репутация: 4
Всего: 259



Цитата(Gold Dragon @  20.4.2010,  10:12 Найти цитируемый пост)
Или что-то типа <col> у которого нет </col> 

Все теги имеют закрывающий тег. 
То, что для некоторых его можно не писать - это послабляющий фактор, но никак не мешает тебе его закрыть.

Добавлено через 2 минуты и 6 секунд
Черт, подумал и понял проблему...
То есть выкусил типа
Код

<col>BlahBlah
<tr><td>Blah2


И по логике, получается, что col надо закрыть smile
Сложно... Чуть ли не парсер писать надо. 
PM MAIL   Вверх
Gold Dragon
Дата 20.4.2010, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



вот именно, писать парсинг... :( ну или сделать ограничения не теги


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
brother79
Дата 20.4.2010, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Цитата(Gold Dragon @  20.4.2010,  12:00 Найти цитируемый пост)
в общем начал колдовать.. Но столкнулся с ещё одной бедой.. А если есть таблица? Тут не только нужно считать теги но и структуру считать.. В общем ужас smile 


Если у тебя документ корректный - то ты знаешь, какие теги должны иметь закрывающийся, а какие нет, например <br>, если же какой-то м.... пишет не закрытый <td> или ещё чего, ты на это универсальную прогу не придумаешь. Я бы предложил - нормальный код парсить или делать препроход и закрывать те же <td> перед <tr>


--------------------
PM MAIL WWW   Вверх
Gold Dragon
Дата 20.4.2010, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



я пишу модуль вывода краткого содержимого старей/новостей  для CMS. И поэтому модуль будут использовать как угодно и где угодно...

скорее всего нужно писать с простого и по мере новых версий вводить новые теги.. другого выхода пока не вижу. Пока будут получаться неоправданные затраты

Это сообщение отредактировал(а) Gold Dragon - 20.4.2010, 11:57


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
ksnk
Дата 20.4.2010, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 12
Всего: 386



Gold Dragon, Есть мысль - заставить юзера(юзеровый броузер) самого впилить все нужные теги...
Новости - это кусочки откопипащеных html'ей? Тогда нужно просто вставить этот текст в какой-то фрейм в html документе, на клиентской стороне у самого "редактора", а потом брать с собой на сервер то, что броузер уже успел "открыть-закрыть". Просто у броузера уже есть механизм исправления корявого кода и им вполне можно пользоваться  smile Заодно это будет последним китайским предупреждением редактору новости - действительно ли вот это и есть то, что хочется показать народу?...

C кодом на сервере нужно, конечно, проделать много дополнительных телодвижений - stripTags для непонятных тегов, очистка понятных тегов от странного и лишнего форматирования и протчий клининг...


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
SickFxck
Дата 21.4.2010, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Цитата(smartov @  20.4.2010,  10:45 Найти цитируемый пост)
Черт, подумал и понял проблему...
То есть выкусил типа
<col>BlahBlah
<tr><td>Blah2

Я до сих пор не вижу проблемы. В данном случае вы просто неправильно "откусили" вот и всё. "Кусать" надо до тех пор, пока не закроются все теги, попавшие в текст, длиной 150 символов. Да, строка может получиться длиннее 150-ти символов, но зато тут виден какой-то алгоритм.

Ещё раз спрашиваю: какой алгоритм выбрал тредстартер?

Добавлено через 3 минуты и 45 секунд
Сложнее всего ответить на вопрос: «а что вообще такое «подстрока гипертекста»? Что вообще вы хотите увидеть, попытавшись получить «150 символов таблицы»? Я смысла в этом вообще вижу мало.
PM MAIL   Вверх
smartov
Дата 21.4.2010, 21:39 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


свой собственный
****


Профиль
Группа: Экс. модератор
Сообщений: 4225
Регистрация: 2.2.2006
Где: NJ

Репутация: 4
Всего: 259



Цитата(SickFxck @  21.4.2010,  21:08 Найти цитируемый пост)
надо до тех пор, пока не закроются все теги, попавшие в текст, длиной 150 символов. Да, строка может получиться длиннее 150-ти символов, но зато тут виден какой-то алгоритм.

Очень класно. Обрежем 150 символов, но не 150 символов. 
Соответствие решения техзаданию даже близко не валяется. 


Цитата(SickFxck @  21.4.2010,  21:08 Найти цитируемый пост)
Я до сих пор не вижу проблемы. 

А я вижу. Раз просят 150, надо сделать все, чтобы было максимально близко, а не делать как получится, потому что так удобнее
PM MAIL   Вверх
SickFxck
Дата 21.4.2010, 21:50 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



smartov, ответь на вопросы:
Цитата(SickFxck @  21.4.2010,  21:08 Найти цитируемый пост)
Сложнее всего ответить на вопрос: «а что вообще такое «подстрока гипертекста»? Что вообще вы хотите увидеть, попытавшись получить «150 символов таблицы»? Я смысла в этом вообще вижу мало. 

А уже только потом можно будет поговорить о реализации.
PM MAIL   Вверх
smartov
Дата 22.4.2010, 07:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


свой собственный
****


Профиль
Группа: Экс. модератор
Сообщений: 4225
Регистрация: 2.2.2006
Где: NJ

Репутация: 4
Всего: 259



SickFxck, мне задание очевидно - его бизнес логика сродни тому, почему у нас на винграде при нажатии кнопки "быстрая цитата" скрипт вставляет цитируемый текст без форматирования, а должен бы с ним. Если у тебя еще есть вопросы - задавай их ТС, а не мне.
PM MAIL   Вверх
SickFxck
Дата 22.4.2010, 07:51 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Цитата(smartov @  22.4.2010,  07:17 Найти цитируемый пост)
мне задание очевидно - его бизнес логика сродни тому, почему у нас на винграде при нажатии кнопки "быстрая цитата" скрипт вставляет цитируемый текст без форматирования, а должен бы с ним

То, что ты не можешь точно описать, не существует.

Цитата(smartov @  22.4.2010,  07:17 Найти цитируемый пост)
Если у тебя еще есть вопросы - задавай их ТС, а не мне. 

Тогда просьба не оценивать чужие предложения на соответствие "техзаданию" автора:
Цитата(smartov @  21.4.2010,  21:39 Найти цитируемый пост)
Соответствие решения техзаданию даже близко не валяется. 

PM MAIL   Вверх
smartov
Дата 22.4.2010, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


свой собственный
****


Профиль
Группа: Экс. модератор
Сообщений: 4225
Регистрация: 2.2.2006
Где: NJ

Репутация: 4
Всего: 259



Цитата(SickFxck @  22.4.2010,  07:51 Найти цитируемый пост)
Тогда просьба не оценивать чужие предложения на соответствие "техзаданию" автора:

Согласен. Прошу прощения. Может автору действительно подходит твой алгоритм.
PM MAIL   Вверх
Gold Dragon
Дата 27.4.2010, 07:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



Извините. был занят... Может я не совсем правильно всем объяснил... вот на примере

есть примеры следующего контекста

Код

<table>
<tr><td>Строка 1</td></tr>
<tr><td>Строка 2</td></tr>
<tr><td>Строка 3</td></tr>
<tr><td>Строка 4</td></tr>
<tr><td>Строка 5</td></tr>
<tr><td>Строка 6</td></tr>
</table>


Код

<ul>
<li>Строка 1</li>
<li>Строка 2</li>
<li>Строка 3</li>
<li>Строка 4</li>
<li>Строка 5</li>
<li>Строка 6</li>
</ul>


Код

<p>Строка 1</p>
<p>Строка 2</p>
<p>Строка 3</p>
<p>Строка 4</p>
<p>Строка 5</p>
<p>Строка 6</p>


Сам текст может иметь любые стили форматирования. И как видно, нужно не только закрывать теги, но и "научить" парсер в каком порядке их закрывать. И строка само собой получится более 150 символов.. Нужно сохранять 150 текста smile

Добавлено через 2 минуты и 48 секунд
интересный вариант предложил brother79, осталось понять логику как это реализовать


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
SelenIT
Дата 27.4.2010, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 8
Всего: 401



Если в лоб, можно попробовать тупо вырезать без учета тегов (напр., регуляркой типа '/([^<>](<[^<>]*>)*){0,150}/s'), а на результат натравить какой-нибудь tidy_repair_string (пусть сам чинит покоцаную разметку;) и из результата вырезать всё между <body>...</body>. Возможно, как вариант, вместо Tidy - DOMDocument::loadHTML (не проверял, поэтому не уверен).

Но вообще подход рискованный. Если это для новых статей/новостей, которые вводятся через WYSIWYG-редактор, лично я бы сделал как-нибудь так: для краткого содержания завел бы отдельное поле (тоже WYSIWYG'овое) и по достижении нужного лимита значением innerText.length/textContent.length основного поля копировал бы innerHTML основного поля туда яваскриптом, оставив редактору новости возможность вручную поменять его на что-то более осмысленное (напр., заменить обрезок таблицы на краткую аннотацию к ней).


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
SickFxck
Дата 27.4.2010, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Через стек просто делается:
Код

function htmlSubstr($html, $length)
{
    $out = '';
    $arr = preg_split('/<(.+?)>/s', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
    $tagStack = array();

    for($i = 0, $l = 0; $i < count($arr); $i++) {
        if( $i & 1 ) {

            if( $arr[$i][0] == '/' ) {
                array_pop($tagStack);
            } elseif( substr($arr[$i], -1) != '/' ) {
                array_push($tagStack, $arr[$i]);
            }

            $out .= '<' . $arr[$i] . '>';

        } else {
            
            if( ($l += strlen($arr[$i])) >= $length ) {
                $out .= substr($arr[$i], 0, $l - $length);
                break;
            } else {
                $out .= $arr[$i];
            }
     
        }
    }

    while( ($tag = array_pop($tagStack)) !== NULL )
    {
        $out .= '</' . $tag . '>';
    }

    return $out;
}

PM MAIL   Вверх
SelenIT
Дата 27.4.2010, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 8
Всего: 401



Кстати,
Цитата(smartov @  20.4.2010,  10:45 Найти цитируемый пост)
Все теги имеют закрывающий тег. 
То, что для некоторых его можно не писать - это послабляющий фактор, но никак не мешает тебе его закрыть.

справедливо для XML (включая XHTML как application/xhtml+xml), но не для HTML (включая XHTML как text/html). В HTML для пустых (принципиально не имеющих содержимого) тегов закрывающий тег именно что запрещен. И <col> - как раз один из таких тегов;)

По сабжу, в первом приближении работает и такое:
Код

    $limit = 150;
    preg_match('/((<[^<>]*>)*(\s+|(&#?\w+;)|[^<>\s])){0,'.$limit.'}/su', $text, $m);
    $html = tidy_repair_string($m[0].'&hellip;',array(),'utf8');
    preg_match('/<body>(.*)<\/body>/isu', $html, $m);
    echo $m[1];

Закрывает всё вроде как надо (проверил на примерах из топика). Правда, нужна поддержка Tidy на сервере и кодировка utf-8 (с cp1251 у меня не получилось). И сбитые rowspan/colspan таблиц не лечит (в принципе, пустяк, таблица-то закрыта, вёрстка дальше не поплывёт)...

Это сообщение отредактировал(а) SelenIT - 27.4.2010, 17:57


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
Gold Dragon
Дата 28.4.2010, 07:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



что такое Tidy?


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
Gold Dragon
Дата 28.4.2010, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



SickFxck, твой код практически отлично работает.. не пробовал на таблицах, но с другими элементами вроде пащет.. Правда <IMG> не проверил... А так всё открывается и закрывается.. 

НО(!)

- задаваемый размер не соответствует реальному тексту
- не учтено всякие специальные символы типа &laquo;

SickFxck, можешь пояснить что и как делается в коде? что-то я запутался smile

вот для примера код
Код

<?php

$s =<<<HTML
<h3>Уважаемые посетители, на <u>наших</u> страницах в апреле ... </h3>
<p align="justify">
<span style="color: #ff0000">&laquo;Професс<i>иона</i>льные ОПРОСНИКИ&raquo;</span>, кого-то они <i>направят</i> в выборе <b>профессии</b>, кому-то <b>они</b> помогут оценить возможность перемен для себя!
</p>
HTML;
$aa = htmlSubstr($s, 10);

echo $aa;
echo '<br>----------------<br>'.strlen(strip_tags($aa));

function htmlSubstr($html, $length)
{
    $out = '';
    $arr = preg_split('/<(.+?)>/s', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
    $tagStack = array();
    for($i = 0, $l = 0; $i < count($arr); $i++) {
        if( $i & 1 ) {
            if( $arr[$i][0] == '/' ) {
                array_pop($tagStack);
            } elseif( substr($arr[$i], -1) != '/' ) {
                array_push($tagStack, $arr[$i]);
            }
            $out .= '<' . $arr[$i] . '>';
        } else {
            
            if( ($l += strlen($arr[$i])) >= $length ) {
                $out .= substr($arr[$i], 0, $l - $length);
                break;
            } else {
                $out .= $arr[$i];
            }
     
        }
    }
    while( ($tag = array_pop($tagStack)) !== NULL )
    {
        $out .= '</' . $tag . '>';
    }
    return $out;
}
?>



--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
SickFxck
Дата 28.4.2010, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Цитата(Gold Dragon @  28.4.2010,  08:15 Найти цитируемый пост)
- задаваемый размер не соответствует реальному тексту
- не учтено всякие специальные символы типа &laquo;

Скорее всего это одна и та же проблема.

Вечером выложу исправленный вариант, если ничего другого не найдёшь.

Добавлено через 53 секунды
А если ты работаешь с UTF-8, то там нужно mb-функции использовать.
PM MAIL   Вверх
Gold Dragon
Дата 28.4.2010, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



SickFxck, прокомментируй код.. Хочу разобраться smile 




--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
SelenIT
Дата 28.4.2010, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 8
Всего: 401



Цитата(Gold Dragon @  28.4.2010,  07:29 Найти цитируемый пост)
что такое Tidy? 

Фактически готовый HTML-парсер.

Цитата(Gold Dragon @  28.4.2010,  08:15 Найти цитируемый пост)
не учтено всякие специальные символы типа &laquo;

У меня учтено;)
Цитата

'/((<[^<>]*>)*(\s+|(&#?\w+;)|[^<>\s])){0,'.$limit.'}/su'



--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
SickFxck
Дата 28.4.2010, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Код

function htmlSubstr($html, $length)
{
    $out = '';
    $arr = preg_split('/(<.+?>|&#?\\w+;)/s', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
    $tagStack = array();

    for($i = 0, $l = 0; $i < count($arr); $i++) {
        if( $i & 1 ) {
            if( substr($arr[$i], 0, 2) == '</' ) {
                array_pop($tagStack);
            } elseif( $arr[$i][0] != '&' && substr($arr[$i], -2) != '/>' ) {
                array_push($tagStack, $arr[$i]);
            }

            if( $arr[$i][0] == '&' )
                $l++;

            $out .= $arr[$i];
        } else {
            if( ($l += strlen($arr[$i])) >= $length ) {
                $out .= substr($arr[$i], 0, $l - $length);
                break;
            } else {
                $out .= $arr[$i];
            }
        }
    }

    while( ($tag = array_pop($tagStack)) !== NULL ) {
        $out .= '</' . substr($tag, 1);
    }

    return $out;
}

PM MAIL   Вверх
SickFxck
Дата 28.4.2010, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Цитата(Gold Dragon @  28.4.2010,  08:58 Найти цитируемый пост)
SickFxck, прокомментируй код.. Хочу разобраться 

Если кратко, то, встречая открывающий тег (парный), мы его пихаем в стек, если встретился закрывающий — выталкиваем. Если длина строки превысила допустимое количество — прерываем цикл. После выталкиваем все незакрытые теги.

Я пользуюсь тем, что preg_split($pattern, $subject, -1, PREG_SPLIT_DELIM_CAPTURE) возвращает массив в виде чередующихся строк и подстрок, подходящих под шаблон. То есть, тег всегда будет в нечётных индексах массива, а простой текст — в чётных.

Да и ещё один фикс:
Код

    while( ($tag = array_pop($tagStack)) !== NULL ) {
        $out .= '</' . strtok(substr($tag, 1), " \t>") . '>';
    }


P.S. И заметь, что, например, "&amp;" я считаю одним символом ("&"), а не 5-ю.

Это сообщение отредактировал(а) SickFxck - 28.4.2010, 17:59
PM MAIL   Вверх
Gold Dragon
Дата 29.4.2010, 07:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



боюсь что Tidy не могу использовать. не на всех серверах он установлен. Проверил у своих хостеров, только у одного стоит :(


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
Gold Dragon
Дата 29.4.2010, 10:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



никак не пойму почему количество заданных символов не соответствует реальной обрезке :(
и разница колеблется в случайном порядке, как в большую сторону так и в меньшую


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
SickFxck
Дата 29.4.2010, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Цитата(Gold Dragon @  29.4.2010,  10:37 Найти цитируемый пост)
никак не пойму почему количество заданных символов не соответствует реальной обрезке

Ты про чей вариант?

Свой я уже пояснил:
Цитата(SickFxck @  28.4.2010,  14:40 Найти цитируемый пост)
P.S. И заметь, что, например, "&amp;" я считаю одним символом ("&"), а не 5-ю.

Поэтому нельзя делать проверку с помощью strlen().

Ах да. Действительно есть кое-что. Окончательный вариант:
Код

function htmlSubstr($html, $length)
{
    $out = '';
    $arr = preg_split('/(<.+?>|&#?\\w+;)/s', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
    $tagStack = array();

    for($i = 0, $l = 0; $i < count($arr); $i++) {
        if( $i & 1 ) {
            if( substr($arr[$i], 0, 2) == '</' ) {
                array_pop($tagStack);
            } elseif( $arr[$i][0] == '&' ) {
                $l++;
            } elseif( substr($arr[$i], -2) != '/>' ) {
                array_push($tagStack, $arr[$i]);
            }

            $out .= $arr[$i];
        } else {
            if( ($l += strlen($arr[$i])) >= $length ) {
                $out .= substr($arr[$i], 0, $length - $l + strlen($arr[$i]));
                break;
            } else {
                $out .= $arr[$i];
            }
        }
    }

    while( ($tag = array_pop($tagStack)) !== NULL ) {
        $out .= '</' . strtok(substr($tag, 1), " \t>") . '>';
    }

    return $out;
}


Код

function htmlStrlen($html)
{
    return strlen(preg_replace('/&#?\\w+;/', '?', strip_tags($html)));
}

assert(htmlStrlen(htmlSubstr('HTML-<strong>string</strong>', 6)) == 6);
assert(htmlStrlen(htmlSubstr('&amp;&#xD7;&amp;', 2)) == 2);
assert(htmlStrlen(htmlSubstr('<p class="p1">test &amp; test </p>', 5)) == 5);


Это сообщение отредактировал(а) SickFxck - 29.4.2010, 11:51
PM MAIL   Вверх
Gold Dragon
Дата 29.4.2010, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



теперь код отлично работает на этом этапе smile Но это при условии что код валидный

если есть <img...> а не <img ... /> то появится </img> smile

а можно как то включить в условия чтобы если встретится например тег <myqqq> то просто его игнорировать и оставить в коде?


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
SickFxck
Дата 29.4.2010, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: 1
Всего: 1



Делай массив таких тегов
Код

$single = array('img', ...);


Добавь условие здесь:
Код
} elseif( substr($arr[$i], -2) != '/>' ) {

substr(), strtok(), strtolower(), in_array()...

Это сообщение отредактировал(а) SickFxck - 29.4.2010, 11:59
PM MAIL   Вверх
SelenIT
Дата 29.4.2010, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 8
Всего: 401



Цитата(Gold Dragon @  29.4.2010,  07:39 Найти цитируемый пост)
Проверил у своих хостеров, только у одного стоит :( 

Я думаю, адекватного хостера можно попросить его добавить. Всё-таки стандартные решения надежнее, имхо (хотя бы тем, что не надо самому заводить массивы пустых тегов и разрешенных тегов)...


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
Gold Dragon
Дата 29.4.2010, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



SelenIT, согласен с тобой.. Но не всё так просто ... ни каждый хостер будет доставлять библиотеки по желанию пользователей...

хотя я думаю нужно и этот вариант сделать, а в настройках давать пользователю вариант выбирать... 


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Тексты | Следующая тема »


 




[ Время генерации скрипта: 0.1678 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.