Aviso: DOMDocument :: loadHTML (): htmlParseEntityRef: expecting ';' na Entidade,

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

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

echo $dom;

lança

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
gweg
fonte

Respostas:

147

Para evaporar o aviso, você pode usar 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);
Dewsworld
fonte
92

Aposto que, se você olhar a fonte http://www.somesite.com/, encontrará caracteres especiais que não foram convertidos para HTML. Talvez algo assim:

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

Deveria estar

<a href="/script.php?foo=bar&amp;hello=world">link</a>
mattalxndr
fonte
3
Apenas para expandir isso, se o caractere & estiver no texto e não em um atributo HTML, ele ainda precisa ser escapado para & amp ;. A razão pela qual o analisador está gerando o erro é porque depois de ver um & está esperando um; para encerrar a entidade HTML.
Kyle
21
... e para expandir ainda mais, chamar htmlentities()ou algo semelhante na string resolverá o problema.
Ben
56
$dom->@loadHTML($html);

Isso está incorreto, use o seguinte:

@$dom->loadHTML($html);
Maanas Royy
fonte
26
ou $ dom-> strictErrorChecking = false;
Tjorriemorrie
6
Esta é uma solução terrível, pois você fará com que os erros nesta linha sejam um pesadelo para depurar. A solução da @Dewsworld é muito melhor.
Gerry
para que serve @?
Francisco Corrales Morales
2
Esta é uma solução muito suja e não vai resolver tudo.
Mirko Brunner
1
Embora sua resposta resolva o problema, a linha "Isso está incorreto" é, por si só, incorreta.
TecBrat
14

Existem 2 erros: o segundo é porque $ dom não é uma string, mas um objeto e, portanto, não pode ser "ecoado". O primeiro erro é um aviso de loadHTML, causado por sintaxe inválida do documento html a carregar (provavelmente um & ( comercial) usado como separador de parâmetro e não mascarado como entidade com &).

Você ignora e suprime essa mensagem de erro (não o erro, apenas a mensagem!) Chamando a função com o operador de controle de erro "@" ( http://www.php.net/manual/en/idioma.operators.errorcontrol. php )

@$dom->loadHTML($html);
user279583
fonte
12

O motivo do seu erro fatal é DOMDocument não tem um método __toString () e, portanto, não pode ser ecoado.

Você provavelmente está procurando por

echo $dom->saveHTML();
Mike B
fonte
10

Independentemente do eco (que precisaria ser substituído por print_r ou var_dump), se uma exceção for lançada, o objeto deve permanecer vazio:

DOMNodeList Object
(
)

Solução

  1. Definido recovercomo verdadeiro e strictErrorCheckingfalso

    $content = file_get_contents($url);
    
    $doc = new DOMDocument();
    $doc->recover = true;
    $doc->strictErrorChecking = false;
    $doc->loadHTML($content);
    
  2. Use a codificação de entidade do php no conteúdo da marcação, que é a fonte de erro mais comum.

Lorenz Lo Sauer
fonte
1
Na primeira solução você escreveu dom em vez de doc.
Máthé Endre-Botond
funcionou para mim, adicionei apenas $ content = mb_convert_encoding ($ content, 'HTML-ENTITIES', 'UTF-8');
Jacek Pietal
8

substitua o simples

$dom->loadHTML($html);

com o mais robusto ...

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;
    }
David Chan
fonte
8
$html = file_get_contents("http://www.somesite.com/");

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

echo $dom;

tente isso

nmwi22
fonte
3

Outra solução possível é

$sContent = htmlspecialchars($sHTML);
$oDom = new DOMDocument();
$oDom->loadHTML($sContent);
echo html_entity_decode($oDom->saveHTML());
lastYorsh
fonte
Isso não vai funcionar. De acordo com php.net/manual/en/function.htmlspecialchars.php , todos os caracteres especiais html também têm escape. Tome por exemplo este pedaço de código HTML <span>Hello World</span>. Executando isso em htmlspecialcharsirá produzir &lt;span&gt;Hello World&lt/span&gt;que não é mais HTML. DOMDocument :: loadHTML não o tratará mais como HTML, mas como uma string.
Twisted Whisper
Isso funciona para mim:$oDom = new DOMDocument(); $oDom->loadHTML($sHTML); echo html_entity_decode($oDom->saveHTML());
Bartłomiej Jakub Kwiatek
3

Eu sei que esta é uma pergunta antiga, mas se você quiser corrigir os sinais '&' malformados em seu HTML. Você pode usar um código semelhante a este:

$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.
        }
    }
}
Nicolas Bouvrette
fonte
0

Outra solução possível é, talvez seu arquivo seja um arquivo do tipo ASCII, basta alterar o tipo de seus arquivos.

FRANK
fonte
-1

Mesmo depois disso, meu código está funcionando bem, então acabei de remover todas as mensagens de aviso com essa instrução na linha 1.

<?php error_reporting(E_ERROR); ?>
Satyam Gupta
fonte