Php 未返回正则表达式的多个匹配项

Php 未返回正则表达式的多个匹配项,php,regex,Php,Regex,我正在使用TinyMCE,它正在清理时将我的所有属性单引号转换为双引号 这就是我正在编辑的内容 <tr _excel-dimensions='{"row":{"rowHeight":50}}'> <td _excel-styles='{"font":{"size":20,"color":{"rgb":"333333"},"bold":true},"fill":{"fillType":"solid","startColor":"F0F0F0"},"alignment":{"hor

我正在使用TinyMCE,它正在清理时将我的所有属性单引号转换为双引号

这就是我正在编辑的内容

<tr _excel-dimensions='{"row":{"rowHeight":50}}'>
<td _excel-styles='{"font":{"size":20,"color":{"rgb":"333333"},"bold":true},"fill":{"fillType":"solid","startColor":"F0F0F0"},"alignment":{"horizontal":"center"}}' colspan='6'>Affiliate Accounts</td>
</tr>

附属帐户
这就是编辑器在保存后所做的

<tr _excel-dimensions="{&quot;row&quot;:{&quot;rowHeight&quot;:50}}">
<td _excel-styles="{&quot;font&quot;:{&quot;size&quot;:20,&quot;color&quot;:{&quot;rgb&quot;:&quot;333333&quot;},&quot;bold&quot;:true},&quot;fill&quot;:{&quot;fillType&quot;:&quot;solid&quot;,&quot;startColor&quot;:&quot;F0F0F0&quot;},&quot;alignment&quot;:{&quot;horizontal&quot;:&quot;center&quot;}}" colspan="6">Accounts</td>
</tr>

账户
似乎没有办法覆盖TinyMCE中的设置。因此,在将数据保存到数据库时,我转向使用PHP的正则表达式。这是我到目前为止所拥有的,但似乎并没有捕捉到所有的双引号

$content = preg_replace_callback('/<(.*)(\")(.*)(\")(.*)>/miU', function($matches) {
  return "<" . $matches[1] . "'" . html_entity_decode($matches[3]) . "'" . $matches[5] . ">";
}, $content);
$content=preg\u replace\u回调('//miU',函数($matches){
返回“”;
}(单位:$content);
它正在替换json编码的字符串,但不是colspan=“6”


提前感谢您的帮助。

正如我在评论中所说,使用正则表达式解析HTML不是很好,最好使用特殊的库,如。但是,可以构造一个正则表达式来处理正确的HTML

我们的目标是在标记中找到所有双引号字符串。首先,让我们忘记双引号字符串必须位于标记内部的要求。然后我们可以使用这个:

$content = preg_replace_callback('/"(.*?)"/', 
  function($matches) {
    return "'" . html_entity_decode($matches[1]) . "'" 
  }, 
  $content);
现在我们需要添加双引号字符串是否在标记内的检查。为此,我们构造了一个先行表达式,用于检查双引号字符串和文本结尾之间的文本:

  • 那里必须有一个标记关闭
    。这意味着必须有一些非
    字符序列,后跟
    。相应的正则表达式是
    [^]*>
  • 它后面必须有任意数量的完整标记
    。包含单个标记的一组字符的正则表达式是
    [^
    。我们需要重复此组任意次数:
    (?:[^)*
  • 在文本末尾可能还有一些非字符:
    [^]*$
由此产生的前瞻表达式看起来有点可怕,但确实有效:
(?=[^]*>(?:[^)*[^]*$)

最后,我们将此前瞻检查合并到原始正则表达式中:

$content = preg_replace_callback('/"(?=[^<>]*>(?:[^<]*<[^>]*>)*[^<>]*$)(.*?)"/', 
  function($matches) {
    return "'" . html_entity_decode($matches[1]) . "'" 
  }, 
  $content);
$content=preg\u replace\u回调('/“(?=[^]*>(?:[^)*[^]*$)(.*?/”,
函数($matches){
返回“'.”.html_entity_decode($matches[1])。“”
}, 
$content);

您可以在此处查看:

一般来说,用正则表达式解析复杂的数据结构(如html)不是一个好主意。正则表达式的问题在于您使用的是贪婪的修改器,例如
(.*)
,而不是
(.*)
,并且没有在一个标记中处理可能的多个属性。Alex,谢谢。我会尝试一下。我同意,但不确定除了regex之外还有什么其他方法。你有什么建议吗?嗨,Alex,谢谢你的深入解决方案。我使用了DomDocument和query。即使答案不正确,我也会相信你的回答这不是推荐的路线。