zar
11:29 06-06-2003 regexps
сижу вот думаю.
требуется добавлять в текст ссылки на ключевые слова. при этом в тексте присутствует html.
пример:
ключевое слово: journals.ru
ссылка: http://journals.ru
на входе:
<i><b>journals</b>.<font color=ffcc00>ru</font></i>
на выходе:
<i><a href=http://journals.ru><b>journals</b>.<font color=ffcc00>ru</font></a></i>

у кого-нибудь есть идеи?
Комментарии:
Arm0
00:53 08-06-2003
регулярные выражения...
zar
01:01 08-06-2003
я знаю, из темы сообщения это видно .
а вот как его правильно построить?
Dark
07:35 08-06-2003
А всегда ли текст на входе соответствует приведённому шаблону? Имеется ввиду порядок тэгов...
zar
13:50 08-06-2003
в том то и задача, что набор тэгов произволен. т.е. замена должна происходит вне зависимости от тэгов, их вообще может не быть.

есть идея просто разбить входное слово на буквы и между ними вставить предполагаемые шаблоны тэгов, т.е. динамически сгенерировать регу.
Dark
07:37 09-06-2003
Я всё-таки не совсем понимаю, что требуется, но не проще ли через str_replace и забить на все тэги? Это "ru" на конце что, так необходимо?
zar
08:37 09-06-2003
1. причём тут ru? я просто показал как может быть разбито тэгами ключевое слово. выбери любое другое. набор тэгов был тоже произвольный. пример
<font color=ffcc00>D</font><b>ark</b> при ключевом слове Dark.
2. вся задача в том, что на тэги забить нельзя. не тот случай, где можно упростить.
zar
09:15 09-06-2003
несколько кривое решение сделано. криво в плане html, не в той последовательности закрывается последний тэг. но в целом оно работает. также для скорости надо б переписать в ereg_replace.
<?php
  $text = '<font color=ffcc00>D</font><b>ark</b>'; // входной текст
  $key = 'Dark'; // ключевое слово
  $url = 'http://www.journals.ru'; // ссылка
  $template = '(<[^>]+> )*'; // шаблон тэга, поправьте если можно сделать красивее
  $str1 = '';$str2 = '';
  function addslash($c) { // экранируем спец.символы
    $sys = array('.', '*', '+', '?', '(', ')', '[', ']', '{', '}', '^', '$', '\', '|');
    return ((in_array($c, $sys))? '\'.$c:$c);
  }
  for ($i=0;$i<strlen($key);$i++) {  // формируем регу
    $str1 .= ($i==0)? addslash($key[$i]):$template.addslash($key[$i]);
    $str2 .= ($i==0)? $key[$i]:'\'.$i.$key[$i];
  }
  $res = preg_replace(array('!'.$str1.'!Ui'), array('<a href='.$url.'>'.$str2.'</a>'), $text); // реплайсим
  echo $res; // результат.
?>
cadaver
12:10 09-06-2003
В PHP Manual есть такое:

Example 635. Convert HTML to text

// $document should contain an HTML document.
// This will remove HTML tags, javascript sections
// and white space. It will also convert some
// common HTML entities to their text equivalent.

$search = array ("'<script[^>]*?>.*?</script>'si", // Strip out javascript
"'<[\/\!]*?[^<>]*?>'si", // Strip out html tags
"'([\r\n])[\s]+'", // Strip out white space
"'&(quot|#34);'i", // Replace html entities
"'&(amp|#38);'i",
"'&(lt|#60);'i",
"'&(gt|#62);'i",
"'&(nbsp|#160);'i",
"'&(iexcl|#161);'i",
"'&(cent|#162);'i",
"'&(pound|#163);'i",
"'&(copy|#169);'i",
"'&#(\d+);'e"); // evaluate as php

$replace = array ("",
"",
"\\1",
"\"",
"&",
"<",
">",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
"chr(\\1)");

$text = preg_replace ($search, $replace, $document);

А интуиция подсказывает что тут нужен preg_split

Но дальше думать, разумеется, лениво

отредактировано: 09-06-2003 12:13 - cadaver

zar
14:15 09-06-2003
to cadaver:
насколько я помню это пример альтернативы strip_tags.
мне же надо оставить html.

насчет моего решения за день пока катался кое-что передумал, позже сяду, сделаю несколько по-другому.
zar
15:26 09-06-2003
новый кривой вариант:
<?php
  $text = '<b>journals</b><font color=ffcc00>.</font><u>ru</u>';
  $key = 'journals.ru';
  $url = 'http://journals.ru';

  $template = '([\r\n\t ]*<.*>[\r\n\t ]*)*';
  
  $str1 = ''; $str2 = '';
  function addslash($c) {
    $sys = array('.', '*', '+', '?', '(', ')', '[', ']', '{', '}', '^', '$', '\', '|');
    return ((in_array($c, $sys))? '\'.$c:$c);
  }
  for ($i=0;$i<strlen($key);$i++) {
    $str1 .= $template.addslash($key[$i]);
    $str2 .= '\'.sprintf('%02d', $i+1).$key[$i];
  }
  $str1 .= $template;
  $str2 .= '\'.sprintf('%02d', strlen($key)+1);
  $res = preg_replace(array('!'.$str1.'!Si'), array('<a href='.$url.'>'.$str2.'</a>'), $text);
  echo $res;
?>

кривой впервую очередь тем, что форматирует вслепую. попробуйте предположим подставить в $text такие варианты:
1. <p>какой-то текст и journals.</p><p align=right>runet стал больше и еще там ляля-топаля</p>
2. <table><tr><td>11</td><td>journals</td></tr><tr><td colspan=2>.ru</td></tr></table>
и всё станет ясно
но других решений пока не вижу...
cadaver
18:20 09-06-2003
А, если у тебя все настолько запущено что и такие варианты случаются (а ты бы хоть сказал что делаешь, понятней бы было) то попробуй воспользоваться каким-нибудь HTML-парсером (например этим http://anton.concord.ru/ , PHP HTML Parser v.1.3, This very good instrument allows parse HTML or XML code inside your script. It is very easy to use. If you need in another grammar and rules for the parser, then you can write it without parser's code modifications.)
zar
07:51 10-06-2003
да в принципе моего решения мне хватит, единственное сегодня еще наверно приделаю чтобы парсил только внутри заданых тэгов(<p>, <td>, <li> и т.п.).

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

отредактировано: 10-06-2003 07:54 - zar

Dark
05:38 11-06-2003
По крайней мере я понял, что требуется.

$text = '<p>какой-то текст и journals.</p><p align=right>runet стал больше и еще там ляля-топаля</p>';
$key = 'journals.ru';
$url = 'http://journals.ru';

for ($i=1; $i<strlen($key); $i++) {
    $str .= '(<.+?> )*'.preg_quote($key[$i]);
}

$str = '/'.preg_quote($key[0]).$str.'/i';

$txt = preg_replace($str, "<a href='".$url."'>\\0</a>", $text);

echo $txt;

отредактировано: 11-06-2003 05:39 - Dark

zar
07:29 11-06-2003
to Dark:
аналогично не грамотно вставляет ссылку, между <a..> и </a> оказывается </p><p>.
я думаю правильнее просто ограничить, внутри каких тэгов можно парсить(td, p, li, h* и т.п.).
Dark
07:54 12-06-2003
Да, про эту ошибку я знаю... Но не всё идеально в этом мире. У меня хотя бы код короче.
Ограничение по тэгам тут - единственный выход. Почему-то в регулярный выражениях исключения можно задавать только символами, но не их последовательностью.
zar
10:53 12-06-2003
да, короче . пару велосипедов я на бегу изобрёл.

попозже сяду сделаю окончательный вариант.

с этой сессией нет времени сесть подумать...