Рег. выражения: Заменить текст в контенте странице, но только не в тегах и не в ссы.

`p r o x y

Новичок
Рег. выражения: Заменить текст в контенте странице, но только не в тегах и не в ссы.

Доброго времени.

1. Исключить замену в тегах, т.к. искомый текст может находится в src, href, alt, title т.д. атрибутах тега.

2. Исключить замену в тексте ссылок.

Прошу, пожалуйста помогите составить поттерн. Ни как не могу понять как реализовать исключения….
 

Splurov

Новичок
В три этапа:
1. Заменяем в тексте все теги и ссылки, сохраняя их в массив, на «метки». Метка — это <символ, не встречающийся в тексте><число-ключ><символ, не встречающийся в тексте>. Что-то типа такого псевдокода:
Код:
$storage = array();
$i = 1;
$text = preg_replace ('/<.?>/s', function($m){
 $i++;
 $storage[$i] = $m[0];
 return '¦' . $i. '¦';
}, $text);
2. Делаем свою замену (которая не должна затрагивать теги/ссылки).
3. Возвращаем «скрытый» в пункте 1 текст.
 

`p r o x y

Новичок
Благодарю за подсказки, получилось.

Пример реализации замены необходимых участок контента в HTML коде страницы, с исключениями поиска в тегах, js коде и тексте ссылок
PHP:
$text = '
<script language="JavaScript" type="text/javascript">
<!--
	alert("В тексте может быть js код, он будет исключен из поиска");
//-->
</script>
Это тестовый контент страници. <a href="#" alr="внутри тега все будет исключатся">В контенте могут быть ссылки, они будут исключены из поиска.</a> Это тестовый контент страници.';


$text_spl = preg_split( '/(<.*?>)/s', $text, -1, PREG_SPLIT_DELIM_CAPTURE );

$nointegs[] = 'script';
$nointegs[] = 'a';
$next = 0;

$search = 'те';

for ( $x = 0; $x < count( $text_spl ); $x++ ){ 
	foreach ( $nointegs as $nointeg ) {
		if ( !$next && preg_match( '/<\s*' . $nointeg . '\s*.*?>/si', $text_spl[$x] ) ) $next = 1;
		if ( $next && preg_match( '/<\s*\/\s*' . $nointeg . '\s*>/si', $text_spl[$x] ) ) $next = 0;
	}
	
	if ( $next || preg_match( '/^<.*?>$/si', $text_spl[$x] ) || preg_replace('/\s/s', '', $text_spl[$x]) == '' ) continue;
	
	$text_spl[$x] = str_replace( $search, '['.$search.']', $text_spl[$x] );
} 
$text_result = implode( '', $text_spl );

echo "<b>Поиск:</b> " . $search;
echo "\n\n<br>\n\n";
echo "<b>Заменить на:</b> " . '['.$search.']';
echo "\n\n<br><br>\n\n";
echo "<b>Исходный текст:</b><br>\n" . htmlspecialchars( $text );
echo "\n\n<br><br>\n\n";
echo "<b>Результат обработки:</b><br>\n" . htmlspecialchars( $text_result );
 

Вурдалак

Продвинутый новичок
PHP:
$text_spl = preg_split( '/(<!\\[CDATA\\[ .*? \\]\\]> | <.*?>)/xs', $text, -1, PREG_SPLIT_DELIM_CAPTURE );

$nointags= array();
$nointags[] = 'script';
$nointags[] = 'a';

$search = 'те';

$nesting_level = 0;

for($i = 0; $i < count($text_spl); $i++) { 

	if( $i & 1 ) {
		if( in_array(strtok(ltrim($text_spl[$i], '</'), ' >'), $nointags) ) {
			if( substr($text_spl[$i], 0, 2) == '</' ) {
				$nesting_level--;
			} else {
				$nesting_level++;
			}
		}
	} elseif($nesting_level == 0) {
		$text_spl[$i] = str_replace($search, '[' . $search . ']', $text_spl[$i]);
	}	
} 

$text_result = implode('', $text_spl);
 

Вурдалак

Продвинутый новичок
HTML-комментарии тоже можно было бы включить в паттерн, кстати.
 

`p r o x y

Новичок
Вурдалак
В каком плане? Замена в содержимом тегов и так не производится же.
Т.е. Это:
Код:
<!-- комментарии -->
будет проигнорированно.
Онож попадает под обработку
PHP:
 if( $i & 1 ) {
Или я не про то?
 

`p r o x y

Новичок
Верно, не додумал. тогда такой вариант:

PHP:
$text = ' 
<script language="JavaScript" type="text/javascript"> 
<!-- 
	alert("HTML и текст в JS коде будет исключен"); 
//--> 
</script> 
<!-- <b>HTML и текст в комментариях будет исключен</b> <Текст в теге будет исключен> Текст в комментариях будет исключен -->
Текст-текст для замены <Текст в теге будет исключен> <a href="#" alr="Текст внутри тега будет исключен">Текст ссылки будет исключен</a> Текст для замены'; 


$text_spl = preg_split( '/(<!\\[CDATA\\[ .*? \\]\\]> | <!--.*?--> | <.*?>)/xs', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); 

$nesting_level = 0;
$nointags = array(); 
$nointags[] = 'script'; 
$nointags[] = 'a'; 

$search = 'те'; 

for($i = 0; $i < count($text_spl); $i++) {  
	if( $i & 1 ) { 
        if( in_array(strtok(ltrim($text_spl[$i], '</'), ' >'), $nointags) ) { 
            if( substr($text_spl[$i], 0, 2) == '</' ) { 
                $nesting_level--; 
            } else { 
                $nesting_level++; 
            } 
        } 
    } elseif($nesting_level == 0) { 
        //$text_spl[$i] = str_replace($search, '[' . $search . ']', $text_spl[$i]);
		$text_spl[$i] = preg_replace( '/(' . preg_quote( $search ) . ')/ius',  '[\\1]', $text_spl[$i] );
    }     
}  
$text_result = implode('', $text_spl);

echo "<b>Поиск:</b> " . $search; 
echo "\n\n<br>\n\n"; 
echo "<b>Заменить на:</b> " . '['.$search.']'; 
echo "\n\n<br><br>\n\n"; 
echo "<b>Исходный текст:</b><br>\n" . htmlspecialchars( $text ); 
echo "\n\n<br><br>\n\n"; 
echo "<b>Результат обработки:</b><br>\n" . htmlspecialchars( $text_result );
-~{}~ 11.05.10 22:02:

Поправка в этой строчке:
PHP:
$text_spl[$i] = preg_replace( '/(' . preg_quote( $search ) . ')/ius',  '[\\1]', $text_spl[$i] );
на

PHP:
$text_spl[$i] = preg_replace( '/(' . preg_quote( $search, '/' ) . ')/ius',  '[\\1]', $text_spl[$i] );
 
Сверху