PHP:仅在HTML标记之外转义引号(正则表达式)

时间:2009-04-17 06:01:35

标签: php html regex escaping

什么正则表达式可以识别HTML标记之外的双引号(已经过验证)以将它们转义为"

6 个答案:

答案 0 :(得分:6)

没有这样的正则表达。

<p>
  <!-- <a href=" --> is this outside " a tag <!-- "> foo </a> --> or not?
</p>

如果你想这样做,你将不得不使用HTML解析器。由于您已经验证了HTML,因此您可能已经使用了解析器。

答案 1 :(得分:1)

不要使用正则表达式,使用(或写入)解析器。

以下代码假定输入HTML字符串格式正确(如您所述)。请注意,如果遇到无效输入,代码将会中断!

如果您无法确定格式良好,可以尝试PHP Tidy

<?php
$html = '<tag>text "text"<tag attr="value"><!-- "text" --> text</tag> "text".';
echo html_escape_quotes($html);

/* Parses input HTML and escapes any literal double quotes 
   in the text content with &quot;. Leaves comments alone.  */
function html_escape_quotes($html)
{
  $output = "";
  $length = strlen($html);
  $delim  = "<";
  $offset = 0;
  while ($offset < $length) {
    $tokpos = strpos($html, $delim, $offset);
    if ($tokpos === false) $tokpos = $length;

    $token  = substr($html, $offset, $tokpos - $offset);
    $offset = $tokpos;

    if ($delim == "<") {
      $token = str_replace('"', '&quot;', $token);
      $delim = substr($html, $offset, 4) == "<!--" ? "-->" : ">";
    } else {
      $delim = "<";
    }

    $output .= $token;
  }
  return $output;
}
?>

答案 2 :(得分:0)

这会有用吗?

\"(?!\s*\w*>)

答案 3 :(得分:0)

它可能。

你可以用regexp做到这一点,有些东西类似于下面。你将不得不多次运行它,因为这个正则表达式只替换了标签之间的1“with”。

Serach: (\<.+?\>.+?)(")(.+?\</.+?\>)
Replace: $1'$3

但是,更好的方法是利用回调来进行功能替换。只需创建将标签内容发送到函数的RE,然后可以简单地将“替换为您想要的任何内容。”

查看更多信息here。搜索回调。 正如derobert所指出的那样,您可能需要在此之前删除评论:)

答案 4 :(得分:0)

您可以尝试拆分字符串,并使用以下表达式将标记与文本数据分开:

<(?:\?[^?]+\?>|[A-Za-z]+(?:[^">]+|"[^"]*")*|!(?:\[CDATA\[(?:[^\]]+|](?:[^\]]|][^>]))*]]|--(?:[^-]+|-(?!->))*--))>

这将(希望)匹配任何XML PI,元素标记,CDATA和注释块。

所以:

$parts = preg_split('/(<(?:\?[^?]+\?>|[A-Za-z]+(?:[^">]+|"[^"]*")*|!(?:\[CDATA\[(?:[^\]]+|](?:[^\]]|][^>]))*]]|--(?:[^-]+|-(?!->))*--))>)/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$str = '';
foreach ($parts as $part) {
    if ($part[0] == '<') {
        $str .= $part;
    } else {
        $str .= str_replace('"', '&quot;', $part);
    }
}

但我怀疑这是非常有效的。一个真正的解析器会更有效和正确。

答案 5 :(得分:0)

不是最好的(不适用于所有情况)但对我来说足够好:

function quoting(&$data) {
    $quot  = '(["\x93\x94\x84]|\&#8220;|\&#8222;|\&#8221;|\&ldquo;|\&bdquo;|\&rdquo;|\&quo;|\&#34;)';
    $parse = '<q>$2</q>';
    $data  = preg_replace('/="([^"]*)"/', '*%Q:$1%*', $data);
    $data  = preg_replace("/$quot(.*?)$quot/", $parse, $data);
    $data  = preg_replace('/\*%Q:(.*?)%\*/', '="$1"', $data);
}