Упреждающее регулярное выражение php preg_replace

Я пытаюсь заменить амперсанды на своем html-коде, используя preg_replace, но проблема в том, что он ломает встроенный javascript && или URL-адрес javascript, например ?page=test&id=1

Теперь у меня есть этот код, который работает

$amp_replace = array();
$amp_replace[0] = '/(?<=\s)&(?!&)(?!#?[a-z0-9]+;)/';
$amp_replace[1] = '/(?<!&)&(?=\s)/';
$skin = preg_replace($amp_replace, '&amp;', $skin);

Заменяет амперсанды, когда пробел слева или справа. не заменяйте, когда 2 амперсанда подряд (для javascript) или когда следует объект html.

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

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

Не лучше ли было бы просто заменить все амперсанды, если не в тегах сценария javascript? Я пробовал это уже, но без особого успеха

Кто-нибудь знает, как я могу заархивировать это? Спасибо


person Basti    schedule 21.10.2011    source источник
comment
Как эти & вообще туда попали? Разве вы не должны решить эту проблему?   -  person Tim Pietzcker    schedule 21.10.2011
comment
Пользовательский контент. Я знаю, что могу исправить это, написав в каждом из моих php-файлов, чтобы исправить вывод амперсанда. Но в этом особом случае мне это не нужно. Поскольку мое кодирование pp становится достаточно большим, я хочу иметь для этого одно глобальное выражение. Просмотрите весь мой html и замените, если не в тегах скрипта   -  person Basti    schedule 21.10.2011


Ответы (2)


Если вы просто хотите преобразовать '&' в контент и избежать тегов (т. е. значений атрибутов)
и избежать блоков скриптов, в большинстве случаев подойдет что-то вроде приведенного ниже.
Однако это так. следует отметить, что значения атрибутов также должны быть преобразованы.
А для этого требуется гораздо больше работы.

Рабочий образец http://www.ideone.com/9MhCq

<?php

$html=<<<EOD
 <some &ta&g> S&P &&more; and &some; <more> &notme;
  && &#209; &#xa92F;
 <script flavor?>
   val && this & this 
 </script>
 &
EOD;

$rxent = '(?:&(?:[A-Za-z_:][\w:.-]*|\#(?:[0-9]+|x[0-9a-fA-F]+));)';

$rxtag =
'<
 (?:
     \?php\s+.*?\?
  |  (?:
       (?:
           (?:script|style)\s*
         | (?:script|style)\s+(?:".*?"|\'.*?\'|[^>]*?)+\s*
       )> .*? </(?:script|style)\s*
     )
  |  (?:
         /?[A-Za-z_:][\w:.-]*\s*/?
       |  [A-Za-z_:][\w:.-]*\s+(?:".*?"|\'.*?\'|[^>]*?)+\s*/?
       | !(?:DOCTYPE.*?|--.*?--)
     )
 )
 >
';

$rxmain = "~(?xs:((?:$rxtag)+) | ((?!$rxent)&))~";


print "$html\n\n";

$html = preg_replace_callback($rxmain, 'fixamp_cb', $html);

print "$html\n";

function fixamp_cb( $matches ) {
    # Return tags and script blocks unchanged.
    if (isset($matches[1]) && $matches[1])
       return $matches[1];
    return '&amp;';
}

?>
person Community    schedule 22.10.2011

Почему бы не что-то простое, например:

$html = preg_replace('/([^&])&([^&])/', '$1&amp;$2', $html);

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

$html = preg_split('/<\/?script>/', $html);
foreach ($html as $k => $v) {
  if ($piece[0] == "<") {
    $html[$k] = preg_replace('/([^&])&([^&])/', '$1&amp;$2', $v);
  } else {
    $html[$k] = "<script>" . $html[$k] . "</script>";
}

Это потребует некоторой модификации, если ваши теги сценария имеют атрибуты.

Если вы очищаете пользовательский контент, возможно, вам лучше использовать уже доступные инструменты. См. очиститель HTML.

person Gordon    schedule 21.10.2011
comment
$skin var - это мой проанализированный html, поэтому я просматриваю свой дырявый html, к сожалению, в моем случае это не сработает. как работает мой выше, но я хочу, чтобы это было проще, например, заменить все и, если не в тегах скрипта. Я знаю, что мог бы просто заменить каждую из своих функций, но я бы написал это только один раз. - person Basti; 21.10.2011
comment
Также попробовал это с тегами script, но похоже, что я никогда не ошибаюсь, либо ошибка, либо он не заменяет - person Basti; 21.10.2011