从 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 标头与您的元内容类型标签值匹配,因为现代浏览器似乎会忽略元标签,而只信任 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();
}