我想替换html文本中的所有文本节点。我将用一个例子来解释: $ html =“
<div>
<p>
text2 text2 word text2
<span>abcd</span>
text2 text2 word text2
<p>
this is a long, very long statement with punctuations.
</div>
我想将“text2 text2 word text2
”替换为“<span>text2 text2 word text2</span>
”,将“this is a long, very long statement with punctuations.
”替换为“<span>this is a long, very long statement with punctuations.</span>
”
同一个正则表达式应该是什么?
答案 0 :(得分:0)
通常有人建议使用HTML解析器。事实上,这对任务来说更可靠。通常,QueryPath或phpQuery在眼睛上也更容易:
$p = phpQuery::newDocumentHTML($h);
$p->find("p")->not("span")->wrap("span");
但在这种情况下,我失败了。如果你不知道所有魔法jQuery选择器(并且phpQuery没有所有的话),这是一个黑色的艺术。您的案例很难,因为您想要处理单个文本节点。因此,您实际上必须使用DOMDocument单独扫描文档。这肯定是可行的,但对我来说API开销太大了。 :}
所以我跳到了正则表达式的方法,其中有很多谨慎,事实上是可行的:
print preg_replace(
'#(?<!<span)>(\s*)(\w[\w,.\h]+)(\s*)<#',
'>$1<span>$2</span>$3<',
$html);
实际的技巧是lookbehind断言(?<!<span)
所以它不会匹配已经包含在跨度中的文本。它看起来更令人困惑,因为我将它分别与空格\s
和水平\h
空格匹配,并将其包含在更好的输出结构中。您必须调整[\w,.\h]
以包含最后一行中所有可能的额外字符。这是正则表达式方法显示其弱点的地方 - 您不能允许它匹配<
或>
。如果您的文本字符串实际上是段落,则必须撤消\ s和\ h分隔..
再次,适用于您的简单案例。但DOM方法是usually more reliable。