在这样的字符串中:
<body>
<img src="specialpic" />
<p>sometext</p><br>
<img src="/somepic.png" />
<img src="/somepic.png" />
<p>someotherstuff</p>
<img src="/anotherpic.png" />
<img src="/anotherpic.png" />
</body>
如何删除每个重复的img
标记,以便最终字符串如下所示?
<body>
<img src="specialpic" />
<p>sometext</p><br>
<img src="/somepic.png" />
<p>someotherstuff</p>
<img src="/anotherpic.png" />
</body>
答案 0 :(得分:1)
为此使用HTML解析器。请使用DOMDocument
查看此示例。
初始化DOMDocument
并加载您的HTML文件:
$dom = new DOMDocument();
libxml_use_internal_errors(1);
$dom->formatOutput = True;
$dom->loadHTML($html);
初始化两个空数组:$img
将包含唯一的src
值,$toDelete
将包含要删除的重复节点:
$img = $toDelete = array();
使用<img>
标记搜索所有节点:
$nodes = $dom->getElementsByTagName( 'img' );
对于每个找到的节点,将src
属性与$img
数组进行比较:如果找到,请将当前节点添加到$toDelete
,否则将src
值添加到{{1} }}:
$img
最后,执行foreach( $nodes as $node )
{
$src = $node->getAttribute('src' );
if( in_array( $src, $img ) ) $toDelete[] = $node;
else $img[] = $src;
}
循环以删除找到的节点:
foreach
打印生成的HTML:
foreach( $toDelete as $node ) $node->parentNode->removeChild( $node );
请注意echo $dom->saveHTML();
阵列的使用情况。从理论上讲,我们可以直接在第一个$toDelete
内删除节点,但通过这种方式我们减少原始发现集的len,所以跳过下一个节点。
答案 1 :(得分:1)
虽然由于HTML的性质而不完全推荐,但根据您的问题,假设图像标签总是采用相同的格式,或者在比较时字符与字符完全相同,则可以使用子图案。 / p>
试试这个:
$input =<<<EOF
<body>
<img src="specialpic" />
<p>sometext</p><br>
<img src="/somepic.png" />
<img src="/somepic.png" />
<p>someotherstuff</p>
<img src="/anotherpic.png" />
<img src="/anotherpic.png" />
</body>
EOF;
$result = preg_replace('|(<img\s*src=.*?\s*/>\s*)\1*|s', '\1', $input);
结果应该是您所希望的确切输出。请在此处查看:https://3v4l.org/sbgDX
\s*
将匹配任何空格.*?
是对\1*
表示子行模式重复0或更多,在换行后或匹配模式后的任何空格来自this post的灵感。