Это был классный вопрос, потому что он продвигал мысль о DoM.
Я поднял вопрос Как парсеры HTML обрабатывают текст без тегов , который был щедро прокомментирован @ sideshowbarker , что заставило меня задуматься и улучшило мои знания о DoM, особенно о тексте узлы.
Ниже представлен способ, основанный на DoM, для поиска подходящих текстовых узлов и дополнения их тегами 'p'. Есть много текстовых узлов, которые мы должны оставить в покое, например, пробелы, возвраты каретки и переводы строк, которые мы используем для форматирования (который может убрать "uglifier").
<?php
$html = file_get_contents("nodeTest.html"); // read the test file
$dom = new domDocument; // a new dom object
$dom->loadHTML($html); // build the DoM
$bodyNodes = $dom->getElementsByTagName('body'); // returns DOMNodeList object
foreach($bodyNodes[0]->childNodes as $child) // assuming 1 <body> node
{
$text="";
// this tests for an untagged text node that has more than non-formatting characters
if ( ($child->nodeType == 3) && ( strlen( $text = trim($child->nodeValue)) > 0 ) )
{ // its a candidate for adding tags
$newText = "<p>".$text."</p>";
echo str_replace($text,$newText,$child->nodeValue);
}
else
{ // not a candidate for adding tags
echo $dom->saveHTML($child);
}
}
nodeTest.html содержит это.
<!DOCTYPE HTML>
<html>
<body>
<h2><b>Hello World</b></h2>
<p>First</p>
Second
<p>Third</p>
fourth
<p>Third</p>
<!-- comment -->
</body>
</html>
и вывод такой ... Я не удосужился повторить внешние теги. Обратите внимание, что комментарии и форматирование обрабатываются правильно.
<h2><b>Hello World</b></h2>
<p>First</p>
<p>Second</p>
<p>Third</p>
<p>fourth</p>
<p>Third</p>
<!-- comment -->
Очевидно, вам нужно пройти через DoM и повторить поиск / замену в каждом элементе узла, если вы хотите сделать вещь более общей. В этом примере мы останавливаемся только на узле Body и обрабатываем каждый прямой дочерний узел.
Я не уверен на 100%, что код наиболее эффективен, и я могу подумать над этим и обновить, если найду лучший способ.