我想在PHP中将HTML标记添加到HTML字符串中,例如:
<h2><b>Hello World</b></h2>
<p>First</p>
Second
<p>Third</p>
第二个不包含任何html元素,因此系统会在其中添加p标签,预期结果:
<h2><b>Hello World</b></h2>
<p>First</p>
<p>Second</p>
<p>Third</p>
尝试使用PHP简单的HTML DOM Parser,但不知道如何处理它,这是我的想法的例子:
function htmlParser($html)
{
foreach ($html->childNodes() as $node) {
if ($node->childNodes()) {
htmlParser($node);
}
// Ideally: add p tag to node innertext if it does not wrapped with any tag
}
return $html;
}
但是,childNode不会循环进入Second,因为它没有包含在里面的元素,并且不建议正则表达式处理html标签,对它有任何想法吗?
非常感谢,谢谢。
这是一个很酷的问题,因为它促进了对DoM的思考。
我提出了一个由@sideshowbarker慷慨评论的问题How do HTML Parsers process untagged text,这让我思考,并提高了我对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%确定代码是最有效的,我可能会考虑更多,如果我找到更好的方法就更新。
用一种愚蠢的方法来解决这个问题,这是我的代码:
function addPTag($html)
{
$contents = preg_split("/(<\/.*?>)/", $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($contents as &$content) {
if (substr($content, 0, 1) != '<') {
$chars = preg_split("/(<)/", $content, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$chars[0] = '<p>' . $chars[0] . '</p>';
$content = implode($chars);
}
}
return implode($contents);
}
希望有其他优雅的方式,而不是这个,谢谢。
$stringHtml = 'Your received html';
$html = str_get_html(stringHtml);
//Find necessary element and edit it
$exampleText = $html->find('Your selector here', 0)->last_child()->innertext