foreach文で20件のループに、空の21件目が表示されます。

解決済みの質問

foreach文で20件のループに、空の21件目が表示されます。

Yahoo!ショッピング商品検索APIを利用するために以下のスクリプトを作成しました。
ここから=======================================================
#!/usr/bin/perl
use LWP::Simple;

#WEBサービスのURL
$base = "http://shopping.yahooapis.jp/ShoppingWebService/V1/categorySearch";
#WEBサービスのID
$appid = "ここにYahooデベロッパーで取得したアプリIDが入ります";

#XMLを取得
my $category_id_data = get("$base?category_id=1&appid=$appid");

#カテゴリを区切る
if($category_id_data){
$category_id_data =~s/\n//g;
if($category_id_data =~/<Children>(.+)<\/Children>/){@category_id_items = split(/<\/Child>/,$1);}
}

print "Content-type: text/html; charset=UTF-8\n\n";

#カテゴリ名をループ
foreach my $category_id_item ( @category_id_items ){
if($category_id_item=~/<Short>(.+?)<\/Short>/) {$category_Name=$1;}
print "$category_Name<br />\n";
}
exit 0;
ここまで================================================
■my $category_id_dataでgetしたXMLのサンプル
http://shopping.yahooapis.jp/ShoppingWebService/V1/categorySearch?appid=YahooDemo&category_id=1

結果を表示すると結果を20件表示するはずなんですが、
21件目の空のリストが書き出されてしまいます。
このスクリプトを他のWEBサービスで使用すると、
きちんと20件表示されました。

原因は何かわかりますでしょうか。
よろしくお願いいたします。

投稿日時 - 2008-09-06 17:54:35

QNo.4308385

暇なときに回答ください

質問者が選んだベストアンサー

まずは揚げ足取りから。

もともとのXMLには

/y:ResultSet/y:Result/y:Categories/y:Children/y:Child/y:title/y:Short
(ただし,上記xpathで用いられる名前空間接頭辞yは名前空間urn:yahoo:jp:categorySearchを指す)
に該当する要素が21個存在していますから

>結果を表示すると結果を20件表示するはずなんですが、
>21件目の空のリストが書き出されてしまいます。
ではなく
>結果を表示すると結果を21件表示するはずなんですが、
だと思います。

さて,当方環境では
空のリスト(空行)が表示される現象が再現できませんでした。
代わりに,最後にのShort要素の内容が二回繰り返される現象を確認しました。

foreach my $category_id_item ( @category_id_items ){
if($category_id_item=~/<Short>(.+?)<\/Short>/) {
$category_Name=$1;}
print "$category_Name<br />\n";
}

foreach my $category_id_item ( @category_id_items ){
if($category_id_item=~/<Short>(.+?)<\/Short>/) {
$category_Name=$1;
print "$category_Name<br />\n";
}
}

の違いではないでしょうか?
#if文の閉じ括弧}の位置が違う
#最後の要素が終わったあと,()内の条件がfalseと等価になって(この演算子の結果が何になるかは俺は確認してない),print文はその外にあるので,
#Short要素が無い時は代入文が実行されず
#直前の内容が出力される。

##俺の回答を見ていたら解るかも知れないが,俺は正規表現によるXMLのParseプログラムが嫌いです。DOM派です。
##文字参照とか実体参照とかCDATA区間とか,名前空間接頭辞が違う,とかいう状態に変更される可能性も無くはないと思っているので。

投稿日時 - 2008-09-06 22:08:00

お礼

ご回答ありがとうございます。

>#Short要素が無い時は代入文が実行されず
>#直前の内容が出力される。

おっしゃるとおり、この現象が起きていました。
投稿後も怪しい部分を調べていった結果、
提供されるXMLのインデントが半角スペースだったため、
最後に半角スペースだけの塊が残ってしまっていたためでした。
正規表現を使い、タグ外部で半角スペースのみの箇所の半角スペースをすべて掃除したところ、
他のWEBサービスと同様の動きに戻りました(解決)。

$category_id_data =~s/\n//g;
$category_id_data =~s/>[ ]{1,}</></g;

>##文字参照とか実体参照とかCDATA区間とか,名前空間接頭辞が違う,とかいう状態に変更される可能性も無くはないと思っているので。

確かにそうですね。
必ずしもバージョン管理で考慮してもらえるとは限らないので、
個人的にも作りながら思います。
もともとhtml文法とcssを専門としているため、
perlを深く掘り下げたことがないため、
もう少しプログラムの知識があれば、
himajinさんの考え方に近くなると思いますが、
今のところはこのプログラムが自分の限界です。

今回はご教授いただきありがとうございました。
またよろしくお願いします。

投稿日時 - 2008-09-07 01:07:29

2人が「このQ&Aが役に立った」と投票しています

あわせてチェックしたい
  • /\とは? ...
  • s/\$○○$・・・について ...
  • s/\s*$// の意味 ...
PR
【回答募集中】花粉にひと言、物申す![ 詳細 ]

OKWaveのオススメ

教えて弁護士さん!

お金の悩みQ&A特集はこちら