0

我正在尝试使用 preg_replace 在我的 html 侧面替换 & 符号,但问题是它破坏了内联 javascript && 或 javascript url,如 ?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 脚本标签中,那么简单地替换所有 & 符号不是更好吗?我已经尝试过了,但没有真正的成功

有谁知道我如何存档?谢谢

4

2 回答 2

1

如果您只想在内容中转换 '&'并避免使用标签(即:属性值)
并避免脚本块,则以下内容适用于大多数情况。
但是,应该注意,属性值也应该进行转换。
而这样做需要做更多的工作。

工作样本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;';
}

?>
于 2011-10-22T00:17:12.930 回答
0

为什么不做一些简单的事情,比如:

$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 净化器

于 2011-10-21T16:44:23.237 回答