Błędy / ostrzeżenia PHP DOMDocument dotyczące tagów html5

105

Próbowałem przeanalizować kod HTML5, aby ustawić atrybuty / wartości w kodzie, ale wygląda na to, że DOMDocument (PHP5.3) nie obsługuje tagów takich jak <nav>i <section>.

Czy istnieje sposób, aby przeanalizować to jako HTML w PHP i manipulować kodem?


Kod do odtworzenia:

<?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>");

Błąd

Ostrzeżenie: DOMDocument :: loadHTML (): Tag nav nieprawidłowy w Entity, wiersz: 4 w /home/wbkrnl/public_html/new-mvc/1.php w wierszu 17

Ostrzeżenie: DOMDocument :: loadHTML (): sekcja tagów nieprawidłowa w Entity, wiersz: 10 w /home/wbkrnl/public_html/new-mvc/1.php w wierszu 17

Klaas Sangers
źródło
Ops, dla mnie loadHTML($HTML5)zwraca FALSE (błąd)! Muszę zmienić nowe tagi na DIV ... To nie tylko problem "ostrzeżeń" na moim ekranie.
Peter Krauss,
2
Ten problem został zgłoszony w przypadku PHP pod adresem bugs.php.net/bug.php?id=60021, co z kolei wywołało żądanie funkcji w bazowym libxml2: bugzilla.gnome.org/show_bug.cgi?id=761534
cweiske

Odpowiedzi:

193

Nie, nie ma sposobu, aby określić konkretny typ dokumentu do użycia lub zmodyfikować wymagania istniejącego.

Najlepszym wykonalnym rozwiązaniem będzie wyłączenie raportowania błędów za pomocą libxml_use_internal_errors:

$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTML('...');
libxml_clear_errors();
samotny dzień
źródło
1
Ops, dla mnie loadHTML($HTML5)zwraca FALSE (błąd)! Muszę zmienić nowe tagi na DIV ...
Peter Krauss
21
Czy jest jakiś powód, dla którego wbudowany w parser DOM php7 nadal nie obsługuje HTML5? Minęło 6 lat od złożenia tej odpowiedzi.
Super Cat
1
@SuperCat Wszystko zależy od podstawowej biblioteki libxml.
lonesomeday,
6
--- nie wspominając o HTML5 to nie XML, nigdy nie było, nie było i nie będzie ...
Kevin_Kinsey
2
Aktualizacja 2019 : Ostrzeżenie jest nadal uruchamiane, ale loadHTMLteraz akceptują tagi HTML5.
9

Ty też możesz to zrobić

@$dom->loadHTML($htmlString);
Ilker Mutlu
źródło
16
Tłumienie błędów nie jest właściwym sposobem rozwiązania tego problemu.
Klaas Sangers,
6
@KlaasSangers Dopóki nie będziemy mieli nieuszkodzonej implementacji DOM, obawiam się, że tak jest (przez @lub libxml_*)
Dan Lugg
6
tak, w tym konkretnym przypadku moim zdaniem najlepszym rozwiązaniem jest eliminacja błędów. chyba że wiesz, że HTML, który będziesz ładować, powinien być w 100% poprawnym HTML zgodnie z definicją PHP. co z mojego doświadczenia nigdy nie ma miejsca.
hanshenrik
@KlaasSangers ... dlaczego nie?
Nick Manning
PHP8 "Operator @ nie wycisza już błędów krytycznych. Możliwe, że ta zmiana może ujawnić błędy, które ponownie zostały ukryte przed PHP 8. Upewnij się, że ustawiłeś display_errors = Off na serwerach produkcyjnych!" stitcher.io/blog/new-in-php-8
marcus
7

Możesz filtrować błędy otrzymane z parsera. Podobnie jak w przypadku innych odpowiedzi tutaj, wyłącz raportowanie błędów na ekranie, a następnie powtórz błędy i wyświetlaj tylko te, które chcesz:

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

foreach ($errors as $error)
{
    /* @var $error LibXMLError */
}

Oto print_r()pojedynczy błąd:

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

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

Dopasowując się do messagei / lub code, można je dość łatwo odfiltrować.

halfer
źródło
2

Wydaje się, że nie ma sposobu na zabicie ostrzeżeń, ale nie błędów. PHP ma stałe, które mają to robić, ale wydają się nie działać. Oto, co POWINNO działać, ale nie działa, ponieważ (błąd?) ....

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

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

user2782001
źródło
Według tego posta stackoverflow.com/a/41845049/937477 ten błąd został naprawiony
mmmmm
1
Żeby być pedantycznym, to nie jest poprawny HTML5. Elementy niestandardowe muszą mieć łącznik zgodnie ze specyfikacją w3c.github.io/webcomponents/spec/custom/…
Greg
@Greg Dobrze wiedzieć. To tylko test, aby wykazać, że parser xml rozpozna tag nieważny, ale zignoruje go z powodu flagi.
user2782001
0

To zadziałało dla mnie:

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

Jeśli potrzebujesz tagu nagłówka, zmień nagłówek za pomocą znacznika div i użyj identyfikatora. Na przykład:

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

Nie jest to najlepsze rozwiązanie, ale w zależności od sytuacji może się przydać.

Powodzenia.

Emiliano Sangoi
źródło
-5

Tagi HTML5 prawie zawsze używają atrybutów, takich jak identyfikator, klasa i tak dalej. Zatem kod do wymiany będzie wyglądał następująco:

$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);
Sergey Kaluzhsky
źródło