- ベストアンサー
foreach文で20件のループに、空の21件目が表示されます。
- Yahoo!ショッピング商品検索APIを利用するために作成したスクリプトで、foreach文で20件のループを行っています。しかし、21件目の空のリストが表示されてしまいます。このスクリプトは他のWEBサービスでは正常に動作していますが、原因は何でしょうか。
- 質問者はYahoo!ショッピング商品検索APIを利用するためにスクリプトを作成しました。スクリプトではforeach文で20件のループを行っていますが、21件目の空のリストが表示されています。他のWEBサービスでは正常に動作しているため、この現象の原因を知りたいと質問しています。
- スクリプトではforeach文で20件のループを行っていますが、21件目の空のリストが表示されてしまいます。他のWEBサービスでは正常に動作しているため、このスクリプトの原因を特定したいと思っています。質問者はYahoo!ショッピング商品検索APIを利用するためにこのスクリプトを作成しました。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
まずは揚げ足取りから。 もともとの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区間とか,名前空間接頭辞が違う,とかいう状態に変更される可能性も無くはないと思っているので。
お礼
ご回答ありがとうございます。 >#Short要素が無い時は代入文が実行されず >#直前の内容が出力される。 おっしゃるとおり、この現象が起きていました。 投稿後も怪しい部分を調べていった結果、 提供されるXMLのインデントが半角スペースだったため、 最後に半角スペースだけの塊が残ってしまっていたためでした。 正規表現を使い、タグ外部で半角スペースのみの箇所の半角スペースをすべて掃除したところ、 他のWEBサービスと同様の動きに戻りました(解決)。 $category_id_data =~s/\n//g; $category_id_data =~s/>[ ]{1,}</></g; >##文字参照とか実体参照とかCDATA区間とか,名前空間接頭辞が違う,とかいう状態に変更される可能性も無くはないと思っているので。 確かにそうですね。 必ずしもバージョン管理で考慮してもらえるとは限らないので、 個人的にも作りながら思います。 もともとhtml文法とcssを専門としているため、 perlを深く掘り下げたことがないため、 もう少しプログラムの知識があれば、 himajinさんの考え方に近くなると思いますが、 今のところはこのプログラムが自分の限界です。 今回はご教授いただきありがとうございました。 またよろしくお願いします。