Ostrzeżenie: DOMDocument :: loadHTML (): htmlParseEntityRef: expecting ';' w Entity,

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

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

echo $dom;

rzuca

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
źródło

Odpowiedzi:

147

Aby odparować ostrzeżenie, możesz użyć 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
źródło
92

Założę się, że jeśli spojrzysz na źródło http://www.somesite.com/, znajdziesz znaki specjalne, które nie zostały przekonwertowane na HTML. Może coś takiego:

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

Powinien być

<a href="/script.php?foo=bar&amp;hello=world">link</a>
mattalxndr
źródło
3
Aby to rozwinąć, jeśli znak & występuje nawet w tekście i nie jest atrybutem HTML, nadal musi zostać zmieniony na & amp ;. Powodem, dla którego parser zgłasza błąd, jest to, że po zobaczeniu & oczekuje; aby zakończyć jednostkę HTML.
Kyle
21
... a aby rozwinąć dalej, wywołanie htmlentities()lub coś podobnego na łańcuchu rozwiąże problem.
Ben
56
$dom->@loadHTML($html);

To jest niepoprawne, użyj zamiast tego:

@$dom->loadHTML($html);
Maanas Royy
źródło
26
lub $ dom-> strictErrorChecking = false;
Tjorriemorrie
6
To okropne rozwiązanie, ponieważ błędy w tej linii będą koszmarem do debugowania. Rozwiązanie @ Dewsworld jest znacznie lepsze.
Gerry
co to jest @za?
Francisco Corrales Morales,
2
To bardzo brudne rozwiązanie, które nie naprawi wszystkiego.
Mirko Brunner
1
Twoja odpowiedź pozwoli obejść problem, ale wiersz „To jest nieprawidłowe” sam w sobie jest niepoprawny.
TecBrat
14

Występują 2 błędy: drugi jest taki, że $ dom nie jest łańcuchem, ale obiektem i dlatego nie może być "powtórzonym". Pierwszy błąd to ostrzeżenie ze strony loadHTML, spowodowane nieprawidłową składnią dokumentu html do załadowania (prawdopodobnie znak & (ampersand) używany jako separator parametrów i niezamaskowany jako encja z &).

Ignorujesz i usuwasz ten komunikat o błędzie (nie błąd, tylko komunikat!), Wywołując funkcję z operatorem kontroli błędów „@” ( http://www.php.net/manual/en/language.operators.errorcontrol. php )

@$dom->loadHTML($html);
user279583
źródło
12

Przyczyną twojego krytycznego błędu jest to, że DOMDocument nie ma metody __toString () i dlatego nie może być powtórzony.

Prawdopodobnie szukasz

echo $dom->saveHTML();
Mike B.
źródło
10

Niezależnie od echa (które musiałoby zostać zastąpione przez print_r lub var_dump), jeśli zostanie wyrzucony wyjątek, obiekt powinien pozostać pusty:

DOMNodeList Object
(
)

Rozwiązanie

  1. Ustaw recoverna true i strictErrorCheckingfalse

    $content = file_get_contents($url);
    
    $doc = new DOMDocument();
    $doc->recover = true;
    $doc->strictErrorChecking = false;
    $doc->loadHTML($content);
    
  2. Użyj kodowania encji php w treści znaczników, które jest najczęstszym źródłem błędów.

Lorenz Lo Sauer
źródło
1
Na pierwszym rozwiązaniu napisałeś dom zamiast doc.
Máthé Endre-Botond
to zadziałało dla mnie Dodałem tylko $ content = mb_convert_encoding ($ content, 'HTML-ENTITIES', 'UTF-8');
Jacek Pietal
8

wymienić proste

$dom->loadHTML($html);

z bardziej wytrzymałym ...

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
źródło
8
$html = file_get_contents("http://www.somesite.com/");

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

echo $dom;

Spróbuj tego

nmwi22
źródło
3

Innym możliwym rozwiązaniem jest

$sContent = htmlspecialchars($sHTML);
$oDom = new DOMDocument();
$oDom->loadHTML($sContent);
echo html_entity_decode($oDom->saveHTML());
lastYorsh
źródło
To nie zadziała. Według php.net/manual/en/function.htmlspecialchars.php , wszystkie znaki specjalne html również są chronione . Weźmy na przykład ten fragment kodu HTML <span>Hello World</span>. Uruchomienie tego w htmlspecialcharsspowoduje, że &lt;span&gt;Hello World&lt/span&gt;nie będzie to już HTML. DOMDocument :: loadHTML nie będzie już traktować go jako HTML, ale jako ciąg.
Twisted Whisper,
U mnie to działa:$oDom = new DOMDocument(); $oDom->loadHTML($sHTML); echo html_entity_decode($oDom->saveHTML());
Bartłomiej Jakub Kwiatek
3

Wiem, że to stare pytanie, ale jeśli kiedykolwiek zechcesz naprawić zniekształcone znaki „&” w kodzie HTML. Możesz użyć kodu podobnego do tego:

$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
źródło
0

Innym możliwym rozwiązaniem jest to, że być może twój plik jest plikiem typu ASCII, po prostu zmień typ swoich plików.

SZCZERY
źródło
-1

Nawet po tym mój kod działa dobrze, więc właśnie usunąłem wszystkie komunikaty ostrzegawcze z tym stwierdzeniem w wierszu 1.

<?php error_reporting(E_ERROR); ?>
Satyam Gupta
źródło