読者です 読者をやめる 読者になる 読者になる

SimpleXMLとマジックメソッド

PHP

 

 で、次の行がとても変態的な内容ですが、実は発言の中に a タグなどのがあると、$valは、さらにaタグのSimpleXMLElementを下の階層に持ちます。そうすると発言からURLなどが抜けてしまうので、一旦 asXML() で XML文字列に落とし込みます。そうすると、 aタグなどもそのまま文字列として帰ってきます。
 
 そこに、strip_tagsでタグを除去し、trimして左右の空白を取り除くことで、純粋な発言内容だけを取り出してきている、というわけです。

 まぁなんというかもっとうまい方法があれば教えてもらいたいものですが、とりあえずはこれでいいかな、という感じです。

SimpleXMLとXMLReaderのまとめ(PHP勉強会で話してきたコード)

 もっとうまい方法ならばありますよ。

<?php
   $xml = @simplexml_import_dom(DOMDocument::loadHTMLFile("http://twitter.com/sotarok"));

   foreach ($xml->xpath("//span[@class='entry-content']") as $val) {
       echo trim($val) ."\n";
}
?>

 これだけで十分です。 

(追記)
この方法ですと、aタグの中「だけ」が落ちちゃうみたいです。なので、aタグの中身ごととろうとするとasXml()使うしかないみたいです。

<?php
$xml=$doc = new DOMDocument();
$doc->loadHTML('<div><span>a<a href="http://example.com">b</a>c</span></div>');
$xml=simplexml_import_dom($doc);
$node=$xml->xpath('//span');
foreach($node as $var){

	echo $var;
}
?>

 
 実はSimpleXMLは子ノードをあらわすメンバとかは全部SimpleXMLElementオブジェクトなんです。
 例えばこのコードを実行してみますと、$xml->channel->item[0]->titleはSimpleXMLElementオブジェクトだよ(意訳)というメッセージがはっきり出ます。
 

<?php
    $xml = simplexml_load_file("http://d.hatena.ne.jp/kagigotonet/rss2");
    var_dump($xml->channel->item[0]->title);
    echo $xml->channel->item[0]->title;
?>

 もちろん、その下のechoではエントリーのタイトルが表示されます。このタネとなっているのがマジックメソッドです。

 マジックメソッドというのは、オブジェクトに対して特定の操作をした際にトリガーされる特殊な関数ですが、このなかで文字列にキャストする際にトリガーされる__toString()を利用してSimpleXMLは文字列にキャストされる際にノードのテキスト表現を生成しているわけです。
 このキャストは文字列を引数に取るような組み込み関数、タイプヒンティングでstringが指定されている関数、あるいはechoによってもおきるので、結果として普段良く目にするSimpleXMLのサンプルが動作するわけです。
 なので最初のコードの場合、中身のテキストを表示するだけならば「echo $var;」だけでOKなんですが、でっかい空白が入ってしまうので最低限の整形としてtrimをかけています。
 ちなみにテキスト表現を得た後で何かしたいというならば(sring)を前につけて型変換を強制的に起こした上で適当な変数に入れてやればOKです。

 実はREST_Clientでそのまま文字列にキャストをするとURLが生成される、というのはこれがヒントになってます。

 注意しなければならないのはxpathメソッドを使った場合ですね。この場合はSimpleXMLElementオブジェクトではなく、SimpleXMLElementオブジェクトを要素にもつ配列が帰ってきます。
 サンプルとしては似たような形になるんですけど。