我需要检测所有不包含文本的<p>
标记,无论<p>
标记包含其他空标记(如<strong>
, <em>
, <span>
…)。然后我需要用
实体替换<p>
标签的内容。
下面的几个例子:
1 -我想转换下面的HTML:<p style="font-size: 16px;"></p>
: <p style="font-size: 16px;"> </p>
2 -我想转换下面的HTML:<p style="font-size: 16px;"><em></em></p>
: <p style="font-size: 16px;"> </p>
3 -我想转换下面的HTML:<p style="font-size: 16px;"><strong><em></em></strong></p>
: <p style="font-size: 16px;"> </p>
4 -我不想转换下面的HTML:<p style="font-size: 16px;"><em>lorem ipsum</em></p>
我已经能够构建一个regex,它只适用于<p>
标签中包含的单个标签(或无):
<p([^>]*)>(?:<[^/>][^>]*></[^>]+>)?</p>
我找不到一种方法来使它与<p>
标签(例3)中叠叠的几个标签一起工作。
使用一个漂亮的DOM解析器:
<?php
$data = <<<DATA
<div>
<p style="font-size: 16px;"></p>
<p style="font-size: 16px;"><em></em></p>
<p style="font-size: 16px;"> </p>
<p style="font-size: 16px;"><strong><em></em></strong></p>
<p style="font-size: 16px;"> </p>
<p style="font-size: 16px;"><em>lorem ipsum</em></p>
</div>
DATA;
$dom = new DOMDocument();
$dom->loadHTML($data, LIBXML_HTML_NOIMPLIED);
#$dom->removeChild($dom->doctype);
$xpath = new DOMXPath($dom);
$lines = $xpath->query("//p[not(normalize-space())]");
foreach ($lines as $line) {
while ($line->hasChildNodes()) {
$line->removeChild($line->firstChild);
}
$line->nodeValue = ' ';
}
echo $dom->saveHTML();
?>
参见 ideone.com上的演示。
生产:
<div>
<p style="font-size: 16px;"> </p>
<p style="font-size: 16px;"> </p>
<p style="font-size: 16px;"> </p>
<p style="font-size: 16px;"> </p>
<p style="font-size: 16px;"> </p>
<p style="font-size: 16px;"><em>lorem ipsum</em></p>
</div>
您可以轻松地在DOM结构中使用JavaScript来完成它,顺便说一下,这比使用正则表达式要快得多,因为regex解析整个字符串,当您在DOM树中浏览时,您正在寻找已经解析的信息(Element的数据如textContent
是静态数据,并且在调用它时不计算)。
var elements = documnet.getElementsByTagName('p'), element, i;
for ( i in elements )
{
element = elements[i];
if ( element instanceof HTMLParagraphElement
&& !element.textContent.trim() )
{
element.innerHTML = ' ';
}
}
好运。