Kesalahan / peringatan PHP DOMDocument pada tag html5

105

Saya telah mencoba untuk mengurai kode HTML5 sehingga saya dapat mengatur atribut / nilai dalam kode, tetapi tampaknya DOMDocument (PHP5.3) tidak mendukung tag like <nav>dan <section>.

Apakah ada cara untuk mengurai ini sebagai HTML di PHP dan memanipulasi kode?


Kode untuk direproduksi:

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

Kesalahan

Peringatan: DOMDocument :: loadHTML (): Tag nav tidak valid di Entity, baris: 4 di /home/wbkrnl/public_html/new-mvc/1.php di baris 17

Peringatan: DOMDocument :: loadHTML (): Bagian tag tidak valid di Entitas, baris: 10 di /home/wbkrnl/public_html/new-mvc/1.php di baris 17

Klaas Sangers
sumber
Ops, bagi saya loadHTML($HTML5)mengembalikan FALSE (gagal)! Saya perlu mengubah tag baru menjadi DIV ... Ini bukan hanya masalah "peringatan" di layar saya.
Peter Krauss
2
Masalah ini telah dilaporkan untuk PHP di bugs.php.net/bug.php?id=60021 yang kemudian memunculkan permintaan fitur di libxml2 yang mendasarinya: bugzilla.gnome.org/show_bug.cgi?id=761534
cweiske

Jawaban:

193

Tidak, tidak ada cara untuk menentukan doctype tertentu untuk digunakan, atau untuk memodifikasi persyaratan yang sudah ada.

Solusi terbaik Anda yang bisa diterapkan adalah menonaktifkan pelaporan kesalahan dengan libxml_use_internal_errors:

$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTML('...');
libxml_clear_errors();
lonesomeday
sumber
1
Ops, bagi saya loadHTML($HTML5)mengembalikan FALSE (gagal)! Saya perlu mengubah tag baru menjadi DIV ...
Peter Krauss
21
Adakah alasan mengapa parser DOM bawaan php7 masih tidak dapat menangani HTML5? Sudah 6 tahun sejak jawaban ini dikirimkan.
Kucing Super
1
@SuperCat Semuanya bergantung pada pustaka libxml yang mendasarinya.
lonesomeday
6
--- belum lagi HTML5 bukanlah XML, tidak pernah, telah, juga tidak akan ...
Kevin_Kinsey
2
Pembaruan 2019 : Peringatan masih diaktifkan namun loadHTMLsekarang sebenarnya menerima tag HTML5.
9

Anda juga bisa melakukannya

@$dom->loadHTML($htmlString);
Ilker Mutlu
sumber
16
Penindasan kesalahan bukanlah cara yang tepat untuk menangani masalah ini.
Klaas Sangers
6
@KlaasSangers Sampai kami memiliki implementasi DOM yang tidak lumpuh, saya khawatir itu (baik melalui @atau libxml_*)
Dan Lugg
6
ya, dalam kasus khusus ini, error supression adalah solusi terbaik, menurut saya. kecuali Anda tahu bahwa HTML yang akan Anda muat, seharusnya HTML yang 100% valid sesuai definisi PHP. yang menurut pengalaman saya, tidak pernah demikian.
Hanshenrik
@Klaasers ... kenapa tidak?
Nick Manning
PHP8 "Operator @ tidak lagi membungkam kesalahan fatal Ada kemungkinan bahwa perubahan ini mungkin mengungkapkan kesalahan yang lagi-lagi disembunyikan sebelum PHP 8. Pastikan untuk menyetel display_errors = Off pada server produksi Anda!" stitcher.io/blog/new-in-php-8
marcus
7

Anda dapat memfilter kesalahan yang Anda dapatkan dari parser. Sesuai jawaban lain di sini, matikan pelaporan kesalahan ke layar, lalu ulangi melalui kesalahan dan hanya tampilkan yang Anda inginkan:

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

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

Berikut adalah print_r()satu kesalahan:

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

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

Dengan mencocokkan pada messagedan / atau code, ini dapat disaring dengan mudah.

halfer
sumber
2

Tampaknya tidak ada cara untuk mematikan peringatan tetapi tidak ada kesalahan. PHP memiliki konstanta yang seharusnya melakukan ini, tetapi tampaknya tidak berfungsi. Inilah yang HARUS berhasil, tetapi tidak karena (bug?) ....

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

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

pengguna2782001
sumber
Menurut posting ini stackoverflow.com/a/41845049/937477 bug itu telah diperbaiki
mmmmm
1
Sekadar bertele-tele, itu bukan HTML5 yang valid. Elemen khusus harus memiliki tanda hubung di dalamnya sesuai dengan spesifikasi w3c.github.io/webcomponents/spec/custom/…
Greg
@ Greg Senang mengetahuinya. Ini hanya tes untuk mendemonstrasikan parser xml akan mengenali tag tersebut tidak valid, tetapi mengabaikannya karena benderanya.
pengguna2782001
0

Ini berhasil untuk saya:

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

Jika Anda membutuhkan tag header, ubah header dengan tag div dan gunakan id. Misalnya:

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

Ini bukan solusi terbaik tetapi tergantung pada situasinya, ini dapat berguna.

Semoga berhasil.

Emiliano Sangoi
sumber
-5

Tag HTML5 hampir selalu menggunakan atribut seperti id, class, dan sebagainya. Jadi kode untuk menggantinya adalah:

$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
sumber