从 PHP 5.4 和 Libxml 2.6 开始,目前有一个更简单的方法
当您像这样加载 html 时
$html->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
在输出中,将没有 doctype、html 或 body 标签
(PHP 5, PHP 7, PHP 8)
DOMDocument::saveHTML — 使用 HTML 格式将内部文档转储到字符串中
从 DOM 表示创建 HTML 文档。此函数通常在从头开始构建新 dom 文档之后调用,如以下示例所示。
node
可选参数,用于输出文档的子集。
返回 HTML,如果发生错误,则返回 false
。
示例 #1 将 HTML 树保存到字符串中
<?php
$doc = new DOMDocument('1.0');
$root = $doc->createElement('html');
$root = $doc->appendChild($root);
$head = $doc->createElement('head');
$head = $root->appendChild($head);
$title = $doc->createElement('title');
$title = $head->appendChild($title);
$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);
echo $doc->saveHTML();
?>
从 PHP 5.4 和 Libxml 2.6 开始,目前有一个更简单的方法
当您像这样加载 html 时
$html->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
在输出中,将没有 doctype、html 或 body 标签
当保存使用 LIBXML_HTML_NOIMPLIED 选项启动的 HTML 片段时,它将最终变成“损坏的”,因为 libxml 需要根元素。libxml 将尝试通过在字符串末尾添加结束标签来修复片段,这将基于它在片段中遇到的第一个打开标签。
例如
<h1>Foo</h1><p>bar</p>
最终将变为
<h1>Foo<p>bar</p></h1>
最简单的解决方法是您自己添加根标签,然后将其删除
$html->loadHTML('<html>' . $content .'</html>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$content = str_replace(array('<html>','</html>') , '' , $html->saveHTML());
如果您从字符串加载 HTML,请确保设置了字符集。
<?php
...
$html_src = '<html><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"></head><body>';
$html_src .= '...';
...
?>
否则字符集将是 ISO-8859-1!
如果您想绕过 <script> 标签问题,可以使用更简单的方法
<?php
$script = $doc->createElement ('script');\
// 创建一个空文本节点强制 <script></script>
$script->appendChild ($doc->createTextNode (''));
$head->appendChild ($script);
?>
<?php
// 使用 DOM 来修复不规范的 HTML。
// 由 Tyson Clugg <[email protected]> 提供的示例
//
// vim: syntax=php expandtab tabstop=2
function tidyHTML($buffer)
{
// 将我们的文档加载到 DOM 对象中
$dom = @DOMDocument::loadHTML($buffer);
// 我们希望获得漂亮的输出
$dom->formatOutput = true;
return($dom->saveHTML());
}
// 启动输出缓冲,使用我们漂亮的
// 回调函数来格式化输出。
ob_start("tidyHTML");
?>
<html>
<p>这就像比较苹果和橙子。
</html>
<?php
// 这将被隐式调用,但我们将
// 手动调用它来说明这一点。
ob_end_flush();
?>
上面的代码删除了不规范的 HTML
<html>
<p>这就像比较苹果和橙子。
</html>
并将其清理为以下内容
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>这就像比较苹果和橙子。
</p></body></html>
为了避免脚本标签被输出为 <script />,您可以使用 DOMDocumentFragment 类
<?php
$doc = new DOMDocument();
$doc -> loadXML($xmlstring);
$fragment = $doc->createDocumentFragment();
/* 使用原始 XML 字符串将脚本元素追加到片段(将以原始形式保留),如果成功,则继续将其插入 DOM 树 */
if($fragment->appendXML("<script type='text/javascript' src='$source'></script>") {
$xpath = new DOMXpath($doc);
$resultlist = $xpath->query("//*[local-name() = 'html']/*[local-name() = 'head']"); /* 查找所有作为 html 元素子元素的 head 元素的命名空间安全方法,应该只返回 1 个匹配项 */
foreach($resultlist as $headnode) // 插入脚本标签
$headnode->appendChild($fragment);
}
$doc->saveXML(); /* 我们的脚本标签仍然将是 <script></script> */
?>
如果您使用 loadHTML() 创建了 DOMDocument 对象(源来自另一个站点),并且想要将您的更改传回浏览器,您应该确保 HTTP Content-Type 标头与您的 meta content-type 标签值匹配,因为现代浏览器似乎忽略了 meta 标签,并且只相信 HTTP 标头。例如,如果您正在读取 ISO-8859-1 文档,而您的 Web 服务器声称是 UTF-8,则需要使用 header() 函数对其进行更正。
<?php
header('Content-Type: text/html; charset=iso-8859-1');
?>
XHTML
如果输出是 XHTML,请使用 saveXML() 函数。
saveHTML 的输出示例
<select name="pet" size="3" multiple>
<option selected>mouse</option>
<option>bird</option>
<option>cat</option>
</select>
使用 saveXML 的 XHTML 符合输出
<select name="pet" size="3" multiple="multiple">
<option selected="selected">mouse</option>
<option>bird</option>
<option>cat</option>
</select>
<?php
function getDOMString($retNode) {
if (!$retNode) return null;
$retval = strtr($retNode-->ownerDocument->saveXML($retNode),
array(
'></area>' => ' />',
'></base>' => ' />',
'></basefont>' => ' />',
'></br>' => ' />',
'></col>' => ' />',
'></frame>' => ' />',
'></hr>' => ' />',
'></img>' => ' />',
'></input>' => ' />',
'></isindex>' => ' />',
'></link>' => ' />',
'></meta>' => ' />',
'></param>' => ' />',
'default:' => '',
// 有时,您也必须对实体进行解码...
'"' => '"',
'&' => '&',
''' => ''',
'<' => '<',
'>' => '>',
' ' => ' ',
'©' => '©',
'«' => '«',
'®' => '®',
'»' => '»',
'™' => '™'
));
return $retval;
}
?>
在这篇文章 http://softontherocks.blogspot.com/2014/11/descargar-el-contenido-de-una-url_11.html 中,我发现了一种使用 DOMDocument、loadHTMLFile 和 saveHTML() 获取 URL 内容的简单方法。
function getURLContent($url){
$doc = new DOMDocument;
$doc->preserveWhiteSpace = FALSE;
@$doc->loadHTMLFile($url);
return $doc->saveHTML();
}