HTML DOM标签上的PHP DOMDocument错误/警告


105

我一直试图解析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():在实体中的标签导航无效,第17行在/home/wbkrnl/public_html/new-mvc/1.php中的第4行

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


对我来说,loadHTML($HTML5)返回FALSE(失败)!我需要将新标签更改为DIV ...这不仅是屏幕上的“警告”问题。
彼得·克劳斯

2
已经在PHPs.bug.php.net/bug.php?id=60021上报告了此问题,这反过来在基础libxml2中产生了功能请求:bugzilla.gnome.org/show_bug.cgi?
id=761534

Answers:


193

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

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

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

1
对我来说,loadHTML($HTML5)返回FALSE(失败)!我需要将新标签更改为DIV ...
Peter Krauss 2014年

21
出于什么原因php7的内置DOM解析器仍然无法处理HTML5?此答案提交至今已有6年了。
超级猫

1
@SuperCat都依赖于底层的libxml库。
lonesomeday'7

6
---更不用说HTML5不是XML,从不曾经,曾经,也不会……
Kevin_Kinsey

2
2019年更新:该警告仍会触发,但是loadHTML现在实际上接受HTML5标签。

9

你也可以

@$dom->loadHTML($htmlString);

16
错误抑制不是解决此问题的正确方法。
克拉斯·桑格斯2014年

6
@KlaasSangers直到我们有了一个不受限制的DOM实现,恐怕它是(通过@还是libxml_*
Dan Lugg 2014年

6
是的,在我看来,在这种特定情况下,错误抑制是最好的解决方案。除非您知道要加载的HTML,否则应该是每个PHP定义中100%有效的HTML。根据我的经验,从来没有这样。
hanshenrik

@KlaasSangers ...为什么不呢?
尼克·曼宁

PHP8“ @运算符不再使致命错误消失,有可能此更改可能揭示在PHP 8之前再次被隐藏的错误。请确保在生产服务器上将display_errors = Off设置为!” itcher.io/blog/new-in-php-8
marcus

7

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

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,可以很容易地将它们过滤掉。


2

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

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

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


根据这个帖子stackoverflow.com/a/41845049/937477这个bug已经修复
MMMMM

1
只是出于学问,这不是有效的HTML5。根据规范w3c.github.io/webcomponents/spec/custom/…,
Greg

@Greg很高兴知道。这只是一个测试,以证明xml解析器将识别标记无效,但由于该标志而将其忽略。
user2782001 '19

0

这对我有用:

$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);

如果需要标题标签,请使用div标签更改标题并使用ID。例如:

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

这不是最佳的解决方案,但根据情况可能会有用。

祝好运。


-5

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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.