警告:DOMDocument :: loadHTML():htmlParseEntityRef:期待';' 在实体中


88
$html = file_get_contents("http://www.somesite.com/");

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

echo $dom;

抛出

Warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity,
Catchable fatal error: Object of class DOMDocument could not be converted to string in test.php on line 10

Answers:


147

要消除警告,您可以使用 libxml_use_internal_errors(true)

// create new DOMDocument
$document = new \DOMDocument('1.0', 'UTF-8');

// set error level
$internalErrors = libxml_use_internal_errors(true);

// load HTML
$document->loadHTML($html);

// Restore error level
libxml_use_internal_errors($internalErrors);

92

我敢打赌,如果您查看源代码,http://www.somesite.com/将会发现尚未转换为HTML的特殊字符。也许是这样的:

<a href="/script.php?foo=bar&hello=world">link</a>

应该

<a href="/script.php?foo=bar&amp;hello=world">link</a>

3
只是为了对此进行扩展,如果&字符在文本中是偶数,而不是HTML属性,则仍然需要将其转义为&amp;。解析器抛出错误的原因是,在看到&之后,它期望a; 终止HTML实体。
凯尔2012年

21
...并进一步扩展,htmlentities()对字符串进行调用或类似操作将解决此问题。

56
$dom->@loadHTML($html);

这是不正确的,请改用:

@$dom->loadHTML($html);

26
或$ dom-> strictErrorChecking = false;
Tjorriemorrie 2011年

6
这是一个糟糕的解决方案,因为您将使这条线上的错误成为调试的噩梦。@Dewsworld的解决方案要好得多。
格里


2
这是一个非常肮脏的解决方案,无法解决所有问题。
Mirko Brunner

1
尽管您的答案可以解决该问题,但“这是错误的”这一行本身是错误的。
TecBrat

14

有两个错误:第二个错误是因为$ dom不是字符串而是一个对象,因此不能被“回显”。第一个错误是来自loadHTML的警告,它是由要加载的html文档的语法无效引起的(可能是与号)用作参数分隔符,而没有被&掩盖为实体)。

您可以通过使用错误控制运算符“ @”(http://www.php.net/manual/zh/language.operators.errorcontrol)调用函数来忽略并抑制该错误消息(不是错误,而只是消息!)。 php

@$dom->loadHTML($html);

12

致命错误的原因是DOMDocument没有__toString()方法,因此无法回显。

您可能正在寻找

echo $dom->saveHTML();

10

不管回显(需要用print_r或var_dump替换),如果引发异常,则对象应保持为空:

DOMNodeList Object
(
)

  1. 设置recover为true和strictErrorCheckingfalse

    $content = file_get_contents($url);
    
    $doc = new DOMDocument();
    $doc->recover = true;
    $doc->strictErrorChecking = false;
    $doc->loadHTML($content);
    
  2. 在标记的内容上使用php的实体编码,这是最常见的错误源。


1
在第一个解决方案中,您编写了dom而不是doc。
马特恩德雷- Botond

这对我有用,我只添加了$ content = mb_convert_encoding($ content,'HTML-ENTITIES','UTF-8');
Jacek Pietal 2014年

8

取代简单

$dom->loadHTML($html);

与更强大的...

libxml_use_internal_errors(true);

if (!$DOM->loadHTML($page))
    {
        $errors="";
        foreach (libxml_get_errors() as $error)  {
            $errors.=$error->message."<br/>";
        }
        libxml_clear_errors();
        print "libxml errors:<br>$errors";
        return;
    }

8
$html = file_get_contents("http://www.somesite.com/");

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

echo $dom;

试试这个


3

另一个可能的解决方案是

$sContent = htmlspecialchars($sHTML);
$oDom = new DOMDocument();
$oDom->loadHTML($sContent);
echo html_entity_decode($oDom->saveHTML());

这是行不通的。根据php.net/manual/en/function.htmlspecialchars.php,所有html特殊字符也都转义了。以这段HTML代码为例<span>Hello World</span>htmlspecialchars&lt;span&gt;Hello World&lt/span&gt;其运行将产生不再是HTML的内容。DOMDocument :: loadHTML不再将其视为HTML而是字符串。
Twisted Whisper

这个工作对我来说:$oDom = new DOMDocument(); $oDom->loadHTML($sHTML); echo html_entity_decode($oDom->saveHTML());
巴特洛梅耶的Jakub Kwiatek

3

我知道这是一个老问题,但是如果您要修复HTML中格式错误的“&”符号,请问。您可以使用类似于以下代码:

$page = file_get_contents('http://www.example.com');
$page = preg_replace('/\s+/', ' ', trim($page));
fixAmps($page, 0);
$dom->loadHTML($page);


function fixAmps(&$html, $offset) {
    $positionAmp = strpos($html, '&', $offset);
    $positionSemiColumn = strpos($html, ';', $positionAmp+1);

    $string = substr($html, $positionAmp, $positionSemiColumn-$positionAmp+1);

    if ($positionAmp !== false) { // If an '&' can be found.
        if ($positionSemiColumn === false) { // If no ';' can be found.
            $html = substr_replace($html, '&amp;', $positionAmp, 1); // Replace straight away.
        } else if (preg_match('/&(#[0-9]+|[A-Z|a-z|0-9]+);/', $string) === 0) { // If a standard escape cannot be found.
            $html = substr_replace($html, '&amp;', $positionAmp, 1); // This mean we need to escape the '&' sign.
            fixAmps($html, $positionAmp+5); // Recursive call from the new position.
        } else {
            fixAmps($html, $positionAmp+1); // Recursive call from the new position.
        }
    }
}

0

另一个可能的解决方案是,也许您的文件是ASCII类型的文件,只需更改文件的类型即可。


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.