|
|
|
| Строка вот так может выглядеть:
<p>здесь текст..........Иной раз слишком длинный</p>
Может вот так:
<p>............................<img...../></p>
Или так:
<table><tr><td>....<table>...</table>..<table>..</table></td></tr></table>
Словом, вложенность может быть произвольная
Надо так сократить текст, чтобы это не привело к ошибочной разметке.
Изначально можно считать что все теги парные и вложены без ошибок (это отдельно проверяется)
Сокращать желательно с хвоста. | |
|
|
|
|
|
|
|
для: Eugene77
(08.02.2008 в 18:59)
| | если просто брать текст между >< примерно так
<?php
$str = <<<TEXT
<p>здесь текст .Иной раз слишком длинный</p>
Может вот так:
<p>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAA<img...../></p>
Или так:
<table><tr><td>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB<table>...</table>..<table>.
.</table>CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCC</td></tr></table>
TEXT;
print preg_replace('#>([^<]{18,})<#se', '">" . str_replace("\\\'", "\'", substr("$1", 0, 15)). "...<"', $str);
?>
| но затрёт всё в тегах типа <script></script> | |
|
|
|
|
|
|
|
для: exp
(08.02.2008 в 20:13)
| | Гм.
Интересно...
Но, если я такое на форуме применю (каждый абзац сокращу на чуть-чуть) думаете красиво получится?
Кажется лучше было бы сократить насколько нужно последний абзац. Если этого не хватит -
выбросить его совсем, и перейти к попытке сократить следующий с конца. | |
|
|
|
|
|
|
|
для: Eugene77
(09.02.2008 в 19:23)
| | Можно попробовать так:
<?php
header('Content-type: text/plain; charset=utf-8');
function ht_substr($ht, $limit, &$pair)
{
if( $limit >= strlen($ht) )
{
return $ht;
}
$ht = preg_split('{(</?(\w+).*?>)}', $ht, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
for($i = 0, $k = 1, $level = 0, $cnt = count($ht); $i < $cnt; $i++, $k++)
{
if( $ht[$i][0] == '<' )
{
$tag = strtolower($ht[$i + 1]);
if( in_array($tag, $pair) )
{
$level += ( $ht[$i][1] == '/' ) ? -1 : +1;
}
$limit -= strlen($ht[$i]);
unset( $ht[$i++ + 1] );
}
else
{
$limit -= strlen($ht[$i]);
}
if( $level <= 0 && $limit <= 0 )
{
return implode(array_slice($ht, 0, $k));
}
}
}
$pair_tags = array('p', 'a');
echo
ht_substr('<p>The quick brown fox jumped over the lazy dog</p><img src="" alt="" />', 10, $pair_tags),
"\r\n",
ht_substr('<p><a href="">The quick brown fox jumped over the lazy dog</a></p> ...', 10, $pair_tags),
"\r\n",
ht_substr('<img src="" alt="" />', 10, $pair_tags);
?>
|
Однако по умолчанию теги одиночные. | |
|
|
|
|
|
|
|
для: Unkind
(09.02.2008 в 20:38)
| | тут так как спрашивается получится сделать только каким-нибудь способом который несколько раз раскладывает и складывает текст
, или просто нетрогая теги урезать только текст.
а так мне слабо-представляется задача , где пришлось-бы так дотошно разобраться в том как построена вложенность тегов. даже с одними только <table> и <p>, максимально что может сделать одно рег-выражение, то эт только найти самые вложенные блоки
<pre>
<?php
$str = <<<T
<p>здесь текст<p>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAA<img...../></p></p>
<table><tr><td>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB<table>CCCCCCCCCCCCCCCCCCCCCCCCCCC</table><table>.
.DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD D</table>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE</td></tr>.
<table>FFFFFFFFFFFFFFFFFFFFF</table></table>
T;
preg_match_all('#<(p|table)>(?>(?:(?!</?\\1>).)*|(?R))+</\\1>#si', $str, $str);
var_dump($str[0]);
?>
</pre>
| здесь не найдёт блоки BBBBBBBBB...... и EEEEEEEEEEEE..... и "здесь текст" | |
|
|
|
|
|
|
|
для: Unkind
(09.02.2008 в 20:38)
| | Есть поучительные дл яменя моменты в вашем коде, но без корректной обработки вложенных тегов мне не обойтись.
Вот такая мысль пришла мне в голову на основе всех этих обсуждений:
<?php
function get_max_len(){
global $max_len;
return $max_len;
}
function shorten($s){
$p = '#(.*)<([a-z][a-z1-6]*)\b[^>]*>([^<>]*)</\\2\b[^>]*>(.*)#is'; // Самый глубоко вложенный tag
for($i=0; $i<18; $i++){
if(strlen($s)<get_max_len()) return $s;
$s = preg_replace_callback($p, create_function('$args', '
$max_len=get_max_len();
if(($d=strlen($args[0]) - strlen($args[3])) >= $max_len) return $args[1].$args[4]; // отбрасываем весь tag
// Сокращаем содержимое тега:
for($a=$args[3], $r=$max_len-$d; strlen($a)>=$r; $a=mb_substr($a,0, mb_strlen($a,"utf-8")-1,"utf-8"));
return $args[1]."<".$args[2].">".$a."</".$args[2].">".$args[4];
'), $s);
}
echo ' Cannot shorten'.$s;
}
$str = "
<p>First text</p>
<b>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAA</b>
<table><tr><td>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB</td></tr><tr><td>CCCCCCC<img ></td></tr></table>
<p>DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDD</p>
<cite>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEE</cite>
<h2>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFF</h2>
";
$max_len=150;
echo htmlspecialchars(shorten($str));
?>
|
Посмотрите, пожалуйста, на предмет разумности такого кода и на предмет возникновения возможных ошибочных ситуаций.Уж больно странно как-то всё это выглядит, хотя вроде сработало несколько раз удачно.
Ещё надо будет подумать об откидывании одиночных тегов, но это я скорее всего сам справлюсь. | |
|
|
|
|
|
|
|
для: Eugene77
(10.02.2008 в 14:57)
| | Непонятен смысл введения функции get_max_len().
На мой взгляд, с помощью create_function() лучше создавать только очень простые функции.
Код привязан с обязательному наличию тегов. Определите $str как
<?php
$str = str_repeat('.', 151);
?>
|
> $a=mb_substr($a,0, mb_strlen($a,"utf-8")-1,"utf-8"));
Это можно было бы сократить до
<?php
$a = mb_substr($a, 0, -1, 'utf-8');
?>
|
> for($i=0; $i<18; $i++)
Почему именно 18?
И вообще зачем Вы ищите самую вложенную пару тегов? Зачем сокращать текст где-то в середине? | |
|
|
|
|
|
|
|
для: Unkind
(10.02.2008 в 22:19)
| | >Непонятен смысл введения функции get_max_len().
Я не сумел придумать ничего лучше этого довольно неприглядного способа, чтобы передать
значение максимальной длины в вызываемую preg_replace_callback ом функцию.
Подскакжите, пожалуйста, как это делается. это тем более желательно ибо максимальная длинна далеко не постоянна и функция будет вызываться с различными значениями этого параметра.
За подсказки -Спасибо!
>И вообще зачем Вы ищите самую вложенную пару тегов? Зачем сокращать текст где-то в середине?
Это не от большого ума. Просто я не сумел придумать ничего другого, чтобы сокращать текст, не касаясь вложенности тегов.
Пока вот такой вариант получается.Что-то ещё можно предпринять? Или указать слабые стороны?
<?
function get_max_len(){
global $max_len;
return $max_len;
}
function shorten($s){
if($s==strip_tags($s)) $s='<p>'.$s.'</p>'; // Это на случай если разметки не окажется
$p = '#(.*)<([a-z][a-z1-6]*)\b[^>]*>([^<>]*)</\\2\b[^>]*>(.*)#is'; // Самый глубоко вложенный tag
for($i=0; $i<50; $i++){
if(strlen($s)<get_max_len()) return $s;
$s1 = preg_replace_callback($p, create_function('$args', '
$max_len=get_max_len();
if(($d=strlen($args[0]) - strlen($args[3])) >= $max_len) return $args[1].$args[4]; // отбрасываем весь tag
// Сокращаем содержимое тега:
for($a=$args[3], $r=$max_len-$d; strlen($a)>=$r; $a = mb_substr($a, 0, -1, "utf-8"));
return $args[1]."<".$args[2].">".$a."</".$args[2].">".$args[4];
'), $s);
if($i==30 or $s==$s1) $s=strip_tags($s,'<p>');
$s=$s1;
}
// на крайний случай, если ничего не помогло
$s=strip_tags($s);
$s=iconv('utf-8','utf-16',$s);
$s=substr($s,0,intval(get_max_len()/2)*2-8);
$s='<p>'.iconv('utf-16','utf-8',$s).'</p>';
}
|
| |
|
|
|
|