2009/05/02

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()
}

最後に添字指定するのは誤解を生む表現で、サンプルとして適切じゃないんじゃないかなと思ったよ。配列に対して配列自身のメソッド以外を実行しようと場合には、配列内の全要素に対して実行された結果が返ってくることに注意。

4 件のコメント:

  1. どうも、ふもです。

    GPathはXPathに比べるとちょっと冗長ですよね。
    findAllとかfindとか使わないといけないですし。
    結果で帰ってくるのが単数なのか複数なのかも意識して使わないと痛い目を見ますね。

    GinAにもXPathを使えるようなライブラリが載っていたような気がしましたが、試せてません^^;
    時間があったらやってみようかな~。

    返信削除
  2. >fumokmmさん
    そうですね。
    慣れの問題かもしれませんが、XmlParser、XmlSlurperを使用した場合は完成形のイメージをしっかり持つように気をつけないといけませんね。

    XmlParserとXmlSlurperでも、node()メソッド呼ぶ、呼ばないとかで結構ひっかかったりしますし。

    返信削除
  3. お だです。

    参考にさせて頂きました。
    トラックバック出来なかったのでコメントにてご連絡します。

    返信削除
  4. >おださん
    ぱっとみ分かりにくいですよね。
    正常には動いているんですが…
    でもGPath的な記述方法になれると逆に読みやすく感じてきたり。
    やはりなれなのか。

    返信削除