php - PHP DOMDocument loadHTML 返回两个 HTML childNodes
问题描述
我在 Visual Studio 中运行 PHP,并希望跨过 HTML 字符串中的各个节点。我使用 loadHTML 将字符串加载到 DOMDocument 并从文档中提取 firstChild,检查它是一个 HTML 节点,但该节点没有任何子节点。
然后我修改了代码以遍历文档的所有子节点,令我惊讶的是,这返回了两个 HTML 节点,第二个具有预期的子节点。这是我应该期待的吗?谁能解释为什么?
附上代码和输出。
enter code here
<?php
$html = '<html><head></head><body>';
$html .= '<h1>Content 1</h1><h2>Content 1.1</h2><h3>Content 1.1.1</h3>';
$html .= '</body></html>';
define ('NEWLINE',"\r\n" );
function recurceHTML ($node, $spaces)
{
$nextIndent = $spaces . ' ';
print ($spaces . $node->nodeName . NEWLINE);
foreach($node->childNodes as $childNode)
{
recurceHTML ($childNode, $nextIndent);
}
}
$dom = DOMDocument::loadHTML($html);
$spaces = ' ';
foreach ($dom->childNodes as $child)
{
recurceHTML ($child, $spaces);
}
$wait = readline();
?>
上面的输出是:
html
html
head
body
h1
#text
h2
#text
h3
#text
解决方案
通过稍微更新代码以更清楚地显示它正在使用的内容,您可以看到数据的来源......
function recurceHTML ($node, $spaces)
{
$nextIndent = $spaces . ' ';
print ($spaces . $node->nodeName."->".$node->nodeType . NEWLINE);
if ( $node->nodeType == 1 ) {
foreach($node->childNodes as $childNode)
{
recurceHTML ($childNode, $nextIndent);
}
}
}
$dom = new DOMDocument();
$dom->loadHTML($html);
$spaces = ' ';
echo $dom->saveHTML().PHP_EOL;
foreach ($dom->childNodes as $child)
{
recurceHTML ($child, $spaces);
}
第一个echo
向您显示它正在使用的实际文档...
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head></head><body><h1>Content 1</h1><h2>Content 1.1</h2><h3>Content 1.1.1</h3></body></html>
如您所见 - 这也将文档类型作为内容的一部分。
然后你有主函数的输出......
html->10
html->1
head->1
body->1
h1->1
#text->3
h2->1
#text->3
h3->1
#text->3
tagName 之后的输出显示节点类型,第一个是 10,它是DOMDocumentType节点(<!DOCTYPE html PUBLIC "-//W3...
),然后第二个是 type 1,XML_ELEMENT_NODE
它是你的<html>
标签。
在您使用loadHTML
时 - 这将始终尝试创建有效的 HTML 文档 - 这包括添加文档类型以及<html>
普通 HTML 页面中需要的标签等。
推荐阅读
- swift - 带有 Swift 5.5 的 Xcode 13.0 将不再使用“import CreateML”语句构建我的项目,如何解决?
- python - pyodbc.OperationalError: ('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]登录超时已过期 (0) (SQLDriverConnect)')
- sql - 如果在 SQL Server 中没有要选择的值,则选择值 = 0
- c# - 如何在 C# 中进行多行输入?
- kotlin - 从 ViewModel 启用/禁用登录按钮
- excel - 从工作簿中的一张工作表复制并复制到另一个目录中的另一本关闭的书
- flutter - Flutter如何将表单数据传递给api
- python-3.x - 是否有可能将标签拖到 tkinter 中同一父标签中的另一个位置?
- flutter - 如何替换 Flutter 中捆绑的 Dart SDK 以在 Apple Silicon (ARM64) 上原生运行?
- javascript - 为什么本机 javascript 函数 sort() 中的第一项 - 在我的数组中是第二项?