Groovy+Xml(その4:XmlParserのサンプルの謎)
XmlParserのサンプルコードとして以下のページが参考になる。
Updating XML with XmlParser – Groovy – Codehaus
さて、このコードの中でずっと疑問だった箇所がある。コードの41行めからを取り上げて話をしたい。
以下のコードを実行すると
def groceries = root.category.findAll{ it.@type == 'groceries' }.item[0] groceries.each { g -> g.value = 'Luxury ' + g.text() }
なぜかgroceries.each()の処理が2回実行される。
すぐ上の処理で…item[0]としているので、item要素の1つ目が取得されるのでeachは1回しか実行されないはずなのに。なんど読んでもこのコードがわからなかった。
さっき散歩している間にふっと気づいた。先のコードは以下のように書き換えられる。
def groceries = root.category.find{ it.@type == 'groceries' }.item groceries.each { g -> g.value = 'Luxury ' + g.text() }
def groceries = root.category.findAll{ it.@type == 'groceries' }[0].item groceries.each { g -> g.value = 'Luxury ' + g.text() }
// これはかなり苦し紛れ def groceries = (root.category.findAll{ it.@type == 'groceries' }*.item)[0] groceries.each { g -> g.value = 'Luxury ' + g.text() }
最後に添字指定するのは誤解を生む表現で、サンプルとして適切じゃないんじゃないかなと思ったよ。配列に対して配列自身のメソッド以外を実行しようと場合には、配列内の全要素に対して実行された結果が返ってくることに注意。
ディスカッション
コメント一覧
どうも、ふもです。
GPathはXPathに比べるとちょっと冗長ですよね。
findAllとかfindとか使わないといけないですし。
結果で帰ってくるのが単数なのか複数なのかも意識して使わないと痛い目を見ますね。
GinAにもXPathを使えるようなライブラリが載っていたような気がしましたが、試せてません^^;
時間があったらやってみようかな~。
>fumokmmさん
そうですね。
慣れの問題かもしれませんが、XmlParser、XmlSlurperを使用した場合は完成形のイメージをしっかり持つように気をつけないといけませんね。
XmlParserとXmlSlurperでも、node()メソッド呼ぶ、呼ばないとかで結構ひっかかったりしますし。
お だです。
参考にさせて頂きました。
トラックバック出来なかったのでコメントにてご連絡します。
>おださん
ぱっとみ分かりにくいですよね。
正常には動いているんですが…
でもGPath的な記述方法になれると逆に読みやすく感じてきたり。
やはりなれなのか。