html5-tags 上的 PHP DOMDocument 错误/警告

Posted

技术标签:

【中文标题】html5-tags 上的 PHP DOMDocument 错误/警告【英文标题】:PHP DOMDocument errors/warnings on html5-tags 【发布时间】:2011-08-30 17:53:30 【问题描述】:

我一直在尝试解析 html5 代码,以便可以在代码中设置属性/值,但似乎 DOMDocument(php5.3) 不支持像 <nav><section> 这样的标签。

有没有办法在 PHP 中将其解析为 HTML 并操作代码?


要重现的代码:

<?php
$dom = new DOMDocument();
$dom->loadHTML("<!DOCTYPE HTML>
<html><head><title>test</title></head>
<body>
<nav>
  <ul>
    <li>first
    <li>second
  </ul>
</nav>
<section>
  ...
</section>
</body>
</html>");

错误

警告:DOMDocument::loadHTML(): 标记 实体中的导航无效,行:4 in /home/wbkrnl/public_html/new-mvc/1.php 第 17 行

警告:DOMDocument::loadHTML(): 标记 实体中的部分无效,行:10 in /home/wbkrnl/public_html/new-mvc/1.php 第 17 行

【问题讨论】:

操作,对我来说 loadHTML($HTML5) 返回 FALSE(失败)!我需要将新标签更改为 DIV... 这不仅仅是我屏幕上“警告”的问题。 这个问题已经在bugs.php.net/bug.php?id=60021 上报告了 PHP,这反过来又在底层 libxml2 中产生了一个功能请求:bugzilla.gnome.org/show_bug.cgi?id=761534 【参考方案1】:

不,无法指定要使用的特定文档类型,或修改现有文档类型的要求。

您最好的可行解决方案是使用libxml_use_internal_errors 禁用错误报告:

$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTML('...');
libxml_clear_errors();

【讨论】:

操作,对我来说 loadHTML($HTML5) 返回 FALSE(失败)!我需要将新标签更改为 DIV... 有什么原因 php7 的内置 DOM 解析器 still 无法处理 HTML5?自提交此答案以来已经 6 年了。 @SuperCat 都依赖于底层的libxml库。 --- 更不用说 HTML5 不是 XML,从来没有,曾经,也不会...... 2019 年更新:警告仍然被触发,但 loadHTML 现在实际上接受 HTML5 标记。【参考方案2】:

你也可以

@$dom->loadHTML($htmlString);

【讨论】:

错误抑制不是处理此问题的正确方法。 @KlaasSangers 在我们有一个非残缺的 DOM 实现之前,恐怕是(通过@libxml_* 是的,在我看来,在这种特定情况下,错误抑制是最好的解决方案。除非您知道要加载的 HTML,否则按照 PHP 的定义,它应该是 100% 有效的 HTML。以我的经验,从来都不是这样。 @KlaasSangers...为什么不呢? PHP8 "@ 运算符不再消除致命错误这一更改可能会显示在 PHP 8 之前再次隐藏的错误。请确保在您的生产服务器上设置 display_errors=Off!" stitcher.io/blog/new-in-php-8【参考方案3】:

您可以过滤从解析器获得的错误。根据此处的其他答案,关闭屏幕上的错误报告,然后遍历错误并仅显示您想要的错误:

libxml_use_internal_errors(TRUE);
// Do your load here
$errors = libxml_get_errors();

foreach ($errors as $error)

    /* @var $error LibXMLError */

这里是一个单一错误的print_r()

LibXMLError Object
(
    [level] => 2
    [code] => 801
    [column] => 17
    [message] => Tag section invalid

    [file] => 
    [line] => 39
)

通过匹配message 和/或code,可以很容易地过滤掉这些。

【讨论】:

【参考方案4】:

似乎没有办法杀死警告而不是错误。 PHP 具有应该执行此操作的常量,但它们似乎不起作用。这是应该工作的,但不是因为(错误?)....

 $doc=new DOMDocument();
 $doc->loadHTML("<tagthatdoesnotexist><h1>Hi</h1></tagthatdoesnotexist>", LIBXML_NOWARNING );
 echo $doc->saveHTML();

http://php.net/manual/en/libxml.constants.php

【讨论】:

根据这篇帖子***.com/a/41845049/937477该bug已修复 只是为了迂腐,这不是有效的 HTML5。根据规范w3c.github.io/webcomponents/spec/custom/…,自定义元素必须有一个连字符 @Greg 很高兴知道。这只是一个测试,以证明 xml 解析器将识别标记无效,但由于标记而忽略它。【参考方案5】:

这对我有用:

$html = file_get_contents($url);

$search = array("<header>", "</header>", "<nav>", "</nav>", "<section>", "</section>");
$replace = array("<div>", "</div>","<div>", "</div>", "<div>", "</div>");
$html = str_replace($search, $replace, $html);

$dom = new DOMDocument();
$dom->loadHTML($html);

如果你需要header标签,用div标签改变header并使用id。例如:

$search = array("<header>", "</header>");
$replace = array("<div id='header1'>", "</div>");

这不是最好的解决方案,但视情况而定。

祝你好运。

【讨论】:

【参考方案6】:

HTML5 标签几乎总是使用 id、class 等属性。所以替换的代码是:

$html = file_get_contents($url);
$search = array(
    "<header", "</header>", 
    "<nav", "</nav>", 
    "<section", "</section>",
    "<article", "</article>",
    "<footer", "</footer>",
    "<aside", "</aside>",
    "<noindex", "</noindex>",
);
$replace = array(
    "<div", "</div>",
    "<div", "</div>", 
    "<div", "</div>",
    "<div", "</div>",
    "<div", "</div>",
    "<div", "</div>",
    "<div", "</div>",
);
$html = str_replace($search, $replace, $html);
$dom = new DOMDocument();
$dom->loadHTML($html);

【讨论】:

以上是关于html5-tags 上的 PHP DOMDocument 错误/警告的主要内容,如果未能解决你的问题,请参考以下文章

同一应用程序上的两种不同语言 PHP 和 Java,Apache 上的 PHP 和 Tomcat 上的 Java

Windows 10 上的 PHP 卷曲,php 5.6.17

php PHP上的端口扫描程序

php PHP上的端口扫描程序

远程 AWS EB 实例上的“php artisan migrate”上的 PHP 致命错误:laravel.log:权限被拒绝

apache 上的 php5,为啥需要 libmod 和 php5?