nantekkotai achieves

過去記事置き場

Yahoo形態素解析の罠

Yahoo形態素解析を使って文字列から名詞句だけ取り出そうとして以下のようなコードを書いた。

require_once "Unserializer.php";
$sentense = htmlspecialchars("text");
$url = "http://jlp.yahooapis.jp/MAService/V1/parse?appid=developerID&results=uniq&filter=9";
$url .= "&sentence=" . urlencode($sentense);
			
$xml = file_get_contents($url);
			
if  ($xml) {
	//返ってきたXMLを連想配列に入れる
	$Unserializer =& new XML_Unserializer();
	$Unserializer->setOption('parseAttributes', TRUE);
	$status = $Unserializer->unserialize($xml);
	$text = "";
        if ($status === true) {
		$res_array = $Unserializer->getUnserializedData();
		foreach ($res_array['uniq_result']['word_list']['word'] as $val) {
			$text .= $val['surface'] . " ";
		}		
	}
}
echo $text; // 結果

それで帰ってくる結果をforeachで回して一つずつ変数に代入しようとすると、たまにエラーが起こってしまう。一体どこで躓いているのかとテストしてみる。
なんと、帰ってくる単語の数が1個だけだと配列の深さが1段階浅くなるのである。
複数の場合は、

['uniq_result'] => Array
    (
        ['word_list'] => Array
            (
                ['word'] => Array
                    (
                        [0] => Array
                            (
                                [count] => 1
                                [surface] => yahoo
                                [reading] => 
                                [pos] => 名詞
                            )
                        [1] => Array
                            (
                                [count] => 1
                                [surface] => 危機
                                [reading] => 
                                [pos] => 名詞
                            )
                    )
            )
    )

となるが、なぜか一つだと、

['uniq_result'] => Array
    (
    [word_list] => Array
            (
                [word] => Array
                    (
                        [count] => 1
                        [surface] => yahoo
                        [reading] => 
                        [pos] => 名詞
                    )
            )
    )

と配列番号が入らない。おかげで、かならずループを回す物だと思い込んでいるとエラーが出る。
foreachの前で

if (array_key_exists(0, $res_array['uniq_result']['word_list']['word'])) {

で['word']以下の配列が複数のものか判別するようにして何とか問題を解決。APIは仕様を統一して欲しいと思った。
それともUnserializerを通したときに変わったのかな。もう腹が減って調べる意欲も湧きませんが、とりあえず問題を迂回できたので良しとした。