在PHP中替换HTML输入的文本节点

时间:2010-12-24 07:27:55

标签: php regex dom domdocument

我想替换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>

同一个正则表达式应该是什么?

1 个答案:

答案 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

相关问题