LoginSignup
1
1

More than 5 years have passed since last update.

SimpleXMLElementをデバッグする

Last updated at Posted at 2014-11-12

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) "こちら"

上記のような出力される。
「お申込みはこちらから」のような連続した文字列は得られないことを知っておく必要がある。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1