- ベストアンサー
XML::XPathでのfor文の記述
たびたびお世話になります。よろしくお願いいたします。 perlでXML文書をHTMLへ変換しています。 ---------------------------------------- <!-- file.xml --> <root> <jouhou> <mei> <toushu>あ</toushu> <toushu>い</toushu> <toushu>う</toushu> </mei> <mei> <toushu>え</toushu> <toushu>お</toushu> <toushu>か</toushu> </mei> </jouhou> </root> ---------------------------------------- このようなXMLの場合に、XML::XPathで「あ」と「え」などの最初に来る<toushu>取りたいのですが 日によって<mei>の数が異なるため、<mei>の数を取得してその数でforをすることにしました。 が、うまくいきません。 my $xp = new XML::XPath( filename => "./file.xml" ); for(my $j=1;$j<=$xp->findvalue("count(//jouhou/mei/toushu)");$j++){ print $j; #←ここでは1と2が出ます。 print $xpath->find('//jouhou/mei[$j]/toushu')->get_node(1)->string_value; } このままでは全く出なく、["$j"]とすると、出るには出るのですが「あ」が2回出てしまいます。 書き方が違うと思うのですが、()でくくってみても出ません。 ちなみに print $xpath->find('//jouhou/mei[1]/toushu')->get_node($j)->string_value; だと、ちゃんと「あ」と「い」が出ました…。 もし、お分かりになれば教えていただきたいです。 お手数をおかけしますが、よろしくお願いいたします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
#1>「あ」と「え」が取り出したいです。 foreach my $node ($xp->find('//jouhou/mei/toushu[1]')->get_nodelist){ print $node->string_value)."\n"; } こんな感じで、 あと、蛇足ですけど for の条件で >$j<=$xp->findvalue("count(//jouhou/mei/toushu)"); のようにすると、条件判定の度に同じことをやり直させることになります。 こういう場合は、件数はループの外で求めるようにした方がよいでしょう。 また、 print $xpath->find("//jouhou/mei[$j]/toushu")->get_node(1)->string_value; でも、一からやり直しさせることになります。 こういう場合は、ノードの(検索結果)リストを作って、それぞれのノードについてループで処理させます。
その他の回答 (3)
- pipipi523
- ベストアンサー率40% (148/365)
「最初の」を見逃しました・・ my $xp = new XML::XPath( filename => "./file.xml" ); for(my $j=1;$i<=$xp->findvalue("count(//jouhou/mei)");$j++){ print $xp->find("//jouhou/mei[$j]/toushu")->get_node(1)->string_value; } ※結果的に ・"count(//jouhou/mei/toushu)"→"count(//jouhou/mei)" ・$xpath→$xp ・'//jouhou/mei[$j]/toushu'→"//jouhou/mei[$j]/toushu" の3点が違いました。
お礼
たびたびの回答ありがとうございます。 本当に助かりました。 また、何かありましたらよろしくお願いします。
- pipipi523
- ベストアンサー率40% (148/365)
シングルクオート''で括ると展開されないのでダメなのだと思います こんな感じではないでしょうか? my $xp = new XML::XPath( filename => "./file.xml" ); for(my $i=1;$i<=$xp->findvalue("count(//jouhou/mei)");$i++){ for(my $j=1;$j<=$xp->findvalue("count(//jouhou/mei[$i]/toushu)");$j++){ print $xp->find("//jouhou/mei[$i]/toushu")->get_node("$j")->string_value; } }
お礼
試してみたら""でうまくいきました。 ありがとうございました。
補足
あ!!そうですよね!そうかもしれないです。 ずっと$jばかりに目が行っていて、気が付きませんでした。 ありがとうございます。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
すいません、結局ループで何を取り出したいのかがよくわかりませんでした。 ・あ,えを取り出したい。 ・あ,い,うを取り出したい。 ・もっと別
補足
書き方が悪くて申し訳ありません…。 「あ」と「え」が取り出したいです。
お礼
お世話になっております。 回答ありがとうございました。 やっとプログラムが完成しつつあるのですが、やはり実行すると速度が遅く、無駄なところが無いか見直していたので、 蛇足で書いていただいたことがとても参考になりそうです。というか、ぜひ参考にさせていただきます。 ありがとうございました。 また、何かありましたらよろしくお願いします。
補足
お礼を先に書いてしまったので、補足にて失礼します。 書いていただいた内容を全て試させていただいたところ、すごく早くなりました!! Benchmarkで調べてみたら10秒くらい違いました。 本当にありがとうございました。