【问题标题】:preg_match_all html tag except tags in double or single quotespreg_match_all html 标记,双引号或单引号中的标记除外
【发布时间】:2015-12-24 09:10:46
【问题描述】:

给定这个 DOM

$html=<<<'EOD'
<div class='container clickable' data-param='{"footer":"<div>Bye</div>","info":"We win"}'>
 <img src='a.jpg' />
</div>
<a href='a.html'>The A</a>
<span></span>
<span data-span-param='{"detailTag":"<span class=\"link\">Anything here</span>"}'>
 <a></a>
</span>  
EOD;  

我正在尝试使用此表达式 preg_match_all html 标签:

$tags = array();
if(preg_match_all('~<\s*[\w]+[^>]*>|<\s*/\s*[\w]+\s*>~im',$html,$matchall,PREG_SET_ORDER)){
   foreach($matchall as $m){
       $tags[] = $m[0];
   }
}  
print_r($tags);

这个表达式的输出是:

数组
(
[0] =>
[1] =>


[2] =>
[3] =>

标签: php html regex pcre


【解决方案1】:

这将匹配所有 html 标签,并且不会捕获用双引号或单引号括起来的标签

<?php
$html=<<<EOD
<div class='container clickable' data-param='{"footer"<div>Bye</div>","info":"We win"}'>
<img src='a.jpg' />
</div>
<a href='a.html'>The A</a>
<span></span>
<span data-span-param='{"detailTag":"<span class=\"link\">Anything here</span>"}'>
<a></a>
</span>
EOD;

$html = preg_replace('~\&lt\;~is','<',$html);
$html = preg_replace('~\&gt\;~is','>',$html);
//$html = preg_replace('~\&quot\;~is','"',$html);
$html = preg_replace('~=\s*\'\s*\'~is','=\'.\'',$html);
$html = preg_replace('~=\s*"\s*"~is','="."',$html);

if(preg_match_all('~((?<==\')(?:.(?!\'))*.)\'|((?<==")(?:.(?!"))*.)"~im',$html,$matchall,PREG_SET_ORDER)){
  foreach($matchall as $m){
    if(preg_match('~\<~is',$m[0],$mtch1)||preg_match('~\>~is',$m[0],$mtch2)){
        $end = $m[0][(strlen($m[0])-1)];
        $replace1 = substr($m[0],0,(strlen($m[0])-1));
        $replace = preg_replace('~"~is','&quot;',$replace1);
        $replace = preg_replace('~<~is','&lt;',$replace);
        $replace = preg_replace('~>~is','&gt;',$replace);
        $html = preg_replace("~".preg_quote(($end.$replace1.$end),'~')."~is",$end.$replace.$end,$html);
    }
  }
}

$tags = array();
if(preg_match_all('~<\s*[\w]+[^>]*>|<\s*/\s*[\w]+\s*>~im',$html,$matchall,PREG_SET_ORDER)){
  foreach($matchall as $m){ 
    $tags[] = $m[0];
  }
}

print_r($tags);
?> 

输出:

Array  
(  
[0] => <div class='container clickable' data-param='{&quot;footer&quot;:&quot;&lt;div&gt;Bye&lt;/div&gt;&quot;,&quot;info&quot;:&quot;We win&quot;}'>  
[1] => <img src='a.jpg' />  
[2] => </div>  
[3] => <a href='a.html'>  
[4] => </a>  
[5] => <span>  
[6] => </span>  
[7] => <span data-span-param='{&quot;detailTag&quot;:&quot;&lt;span class=\&quot;link\&quot;&gt;Anything here&lt;/span&gt;&quot;}'>  
[8] => <a>
[9] => </a>  
[10] => </span>  
)

【讨论】:

    【解决方案2】:

    此正则表达式适用于您的代码,无需额外代码:

    <\s*(?:/\s*)?\w++(?>[^>'"]++|'[^']+'|"[^"]+")*>
    

    DEMO

    【讨论】:

    • 感谢@Alan,这太棒了,我将在我的代码中使用这个表达式。
    【解决方案3】:

    我认为解决这个问题最好的方法是使用递归正则表达式。

    (?!<\s*>)\<(?:(?>[^<>]+)|(?R))*\>
    

    Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-21
      • 1970-01-01
      • 2012-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多