phpQueryでXMLで始まるHTMLのパースでエラー
HTMLのパースを行おうとしたら1行目にあったXMLの記述が原因でエラーが出てきた。
作成日:2018-02-09, 更新日:2020-10-26
下記のようエラー
phpQueryでパースしようとしたら下記のようなエラーが出てきた。
Fatal error: Uncaught exception 'Exception' with message 'Error loading XML markup' in 〇〇〇〇/phpQuery-onefile.php:XXX Stack trace: #0 〇〇〇〇/phpQuery-onefile.php(XXX): DOMDocumentWrapper->loadMarkupXML('<xml version="...') #1 〇〇〇〇/phpQuery-onefile.php(XXX): DOMDocumentWrapper->loadMarkup('<xml version="...') #2 〇〇〇〇/phpQuery-onefile.php(XXX): DOMDocumentWrapper->load('<xml version="...', NULL, NULL) #3 〇〇〇〇/phpQuery-onefile.php(XXX): DOMDocumentWrapper->__construct('<xml version="...', NULL, NULL) #4 〇〇〇〇/phpQuery-onefile.php(XXX): phpQuery::createDocumentWrapper('<xml version="...', NULL) #5 〇〇〇〇/〇〇〇〇.php(XXX): phpQuery::newDocument('<xml version="...') #6 {main} thrown in 〇〇〇〇/phpQuery-onefile.php on line XXX
対象のHTMLファイルを見ると1行目に「<?xml version="1.0" encoding="utf-8"?>」ってのがいた。
ひとまず、これを削除するとパースは出来る。
エラーになっている箇所
エラーメッセージにあるように「phpQuery-onefile.php」の「loadMarkupXML()」内にある「throw new Exception("Error loading XML markup");」ってトコ。
※「phpQuery-onefile.php」をカスタマイズしていなければ424行目だと思う。
ココに入るまでの流れを見ると15行目ぐらいにある「$return = $this->document->loadXML($markup, $libxmlStatic);」ってトコ。
この下にコメントされている文がある。
$return = $this->document->loadXML($markup, $libxmlStatic); // if (! $return) // $return = $this->document->loadHTML($markup);
「loadXML()」で失敗したら「loadHTML()」をさせようとしたけど、やっぱやーめたって感じ。
ひとまずコメント解除。
「loadHTML()」のコメント解除
コメント解除して、再度パースしようとしたら次は下記のようなエラー。
Warning: DOMDocument::loadHTML(): Attempt to load network entity http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtdhtmlParseEntityRef: expecting ';' in Entity, line: 158 in 〇〇〇/phpQuery-onefile.php on line 431
調べると「$this->document->loadHTML($markup);」がよくないらしい。
// if (! $return) // $return = $this->document->loadHTML($markup); // ▼コメント解除して、下記のように修正 if (! $return) $return = $this->document->loadHTML(htmlspecialchars($markup));
ひとまず、これでエラーは出なくなったけど、パースはされない・・・。
調べると文字化けしていた。
文字化け対策
取得したソースを下記のようにUTF8にして「loadHTML()」していたけどダメらしいので、修正。
// $sorce = mb_convert_encoding($sorce, "UTF-8", "auto"); $sorce = mb_convert_encoding($sorce, "HTML-ENTITIES", "auto"); $dom = phpQuery::newDocument($sorce); // 「HTML-ENTITIES」が何者かは知らないが、phpQuery-onefile.php内のコイツをやっても文字化けはしなくなった。 // $this->document->loadHTML(htmlspecialchars($markup));
挫折
文字化けして、再度パースするけど、どうしても・・・パースが出来ない。
解決
諦めようとしたけど・・・よくよく考えたらHTMLのパース時に「loadMarkupXML()」を実行されるのがよくない。
無理やりHTMLのパースをしてくれる関数のほうに誘導したい!ってコトに思い至ってソースを確認。
「phpQuery::newDocument()」から辿ろうとすると「phpQuery::newDocumentHTML()」ってヤツがいた。
修正箇所をすべて元に戻して・・・下記のように修正。
$sorce = mb_convert_encoding($sorce, "UTF-8", "auto"); //$dom = phpQuery::newDocument($sorce); $dom = phpQuery::newDocumentHTML($sorce);