XMLをパースしたSimpleXMLElementをデバッグする
コードだけ欲しい人は下まで読み飛ばして欲しい。
SimpleXMLElementとは
xmlの構文解析で使用するEntity的な物である。
XML文章を変換し最終的にSimpleXMLElementにパースされる。
詳しくはPHPのリファレンスを参照
HTMLを構文解析
HTMLもSimpleXMLElementにパースすることができる。
$domDocument = new DOMDocument();
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'ASCII, JIS, EUC-JP, SJIS, UTF-8');//文字化け対策に全て参照文字に変換
@$domDocument->loadHTML($html);
$xmlString = $domDocument->saveXML();
$xmlObject = simplexml_load_string($xmlString);
パースで来てもデバッグ出来ない
いざパースされたSimpleXMLElementを使用しようとしても目的の値がどのPathに格納されているか分からない場合がある。
するとソースから要素を調べる必要があるが数百行を超えるHTMLを追うのは苦行いがいの何物でもない。
ではパースされたSimpleXMLElementインスタンスをデバッグしようとするが、
var_dumpやprint_rでは反復処理が解決できず、パスがダンプ出来ない。
そのため独自のデバッグclassが必要になった。
ソース
SimpleXMLElementDumper.php
<?php
class SimpleXMLElementDumper {
public function dump($url) {
/* ページ読み込み */
$html = @file_get_contents($url);
if ($html === false) {
echo 'get contents error ' . PHP_EOL;
exit;
}
$xmlObject = $this->_parse($html);
if ($xmlObject instanceof SimpleXMLElement) {
$this->_dumpSimpleXMLElement($xmlObject);
}
}
private function _parse($html) {
$domDocument = new DOMDocument();
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'ASCII, JIS, EUC-JP, SJIS, UTF-8');
@$domDocument->loadHTML($html);
$xmlString = $domDocument->saveXML();
$xmlObject = simplexml_load_string($xmlString);
return $xmlObject;
}
private function _dumpSimpleXMLElement($xmlObject, $xpath = '') {
if ($xmlObject instanceof SimpleXMLElement) {
$xpath .= $xmlObject->getName() . '->';//パンくずリストを作る
echo $xpath . PHP_EOL;
//要素のプロパティを表示
foreach ($xmlObject->attributes() as $key => $value) {
echo $key, '=', $value . PHP_EOL;
}
//要素を表示
var_dump($xmlObject->__toString()) . PHP_EOL;
//子要素がなくなるまで再帰的に呼ぶ
foreach ($xmlObject->children() as $val) {
$this->_dumpSimpleXMLElement($val, $xpath);
}
} else {
echo gettype($xmlObject) . PHP_EOL;
}
}
}
if (isset($argv[1])) {
$url = $argv[1];
} else {
echo 'Refused to display.' . PHP_EOL;
exit;
}
$rd = new SimpleXMLElementDumper();
$rd->dump($url);
使用法はコンソールで第一引数にURLを与えれて実行
php http://qiita.com/
実行すると以下のような出力を得る
html->
string(0) ""
html->head->
string(0) ""
html->head->meta->
charset=UTF-8
string(0) ""
html->head->title->
string(56) "Qiita - プログラマの技術情報共有サービス"
~省略
note
XMLの特性上、特定の入子要素で期待した出力を得られない場合がある。
<span>お申込みは<a href="./reg">こちら</a>から</span>
のような構文をパースすると
span->
string(21) "お申込みはから"
span->a->
href=./reg
string(9) "こちら"
上記のような出力される。
「お申込みはこちらから」のような連続した文字列は得られないことを知っておく必要がある。