Groovy で XML ファイルを書き替えてみる

XML ファイルを書きかえるのに、PowerShell が便利! - お だ のスペース の続き。
コメントにて、Groovy (XmlParser) で XML ファイルを変更する方法を教えて頂いたので調べてみました。


Groovy - Updating XML with XmlParser を見ていると理解出来ないこんなコードがあったので、

def groceries = root.category.findAll{ it.@type == 'groceries' }.item[0]
groceries.each { g ->
    g.value = 'Luxury ' + g.text()
}

すこし調べてみると ゲンゾウさんのページに思いっきり載ってました。
ゲンゾウ用ポストイット: Groovy+Xml(その4:XmlParserのサンプルの謎)
このコードどうなってるのか良く分からなくて、ゲンゾウさんのページを見ても未だしっくりこなくて色々動かしながら自分なりに納得した事を書きます。
(間違ってたらスイマセン、参考にしないで下さい。)
ゲンゾウ用ポストイット: Groovy+Xml(その4:XmlParserのサンプルの謎) より引用

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

これを確かめてみる。

class Test {
  int value
  public Test() {
    this(0)
  }
  public Test(int v) {
    value = v
  }
}

def list = [ new Test(1), new Test(3), new Test() ]
def lv = list.value
list.each { println it.class } // class Test class Test class Test
lv.each { println it.class } // class java.lang.Integer class java.lang.Integer class java.lang.Integer

実行結果を見てみると、確かにそうだった。list に value ってのが無いので list 内の各要素(ここでは、Test クラス)の value を要素とした新しいリストが返されてる。


ってことで、疑問に思ったコード

def groceries = root.category.findAll{ it.@type == 'groceries' }.item[0]

は、
root.category.findAll{ it.@type == 'groceries' } で 要素が一つの リストが返ってきていて、その中身は groceries の Node 。
root.category.findAll{ it.@type == 'groceries' }.item は groceries の Node の item っていう 子Node のリストが要素となる、要素1の新しいリストが返ってくる。(日本語ややこしいな、伝わるかな?)
んでそのリストの 0 番目の要素は、item っていう 子ノード のリスト。
だから、Groovy - Updating XML with XmlParser のサンプルコード は正しいんだよって事かな。


長くなったので、実際に XML を書き替えるコードは次回に載せます。


あと、試してて思った素朴な疑問。メソッドだとダメだったんだけど、プロパティしかダメなのかな?

class Test {
  int value
  public Test() {
    this(0)
  }
  public Test(int v) {
    value = v
  }
  public void addOne() { 
    value += 1
  } 
}
def list = [ new Test(1), new Test(3), new Test() ]
def lv = list.addOne() // 例外が発生