3

I am new to groovy - I am hoping this is a simple thing to solve. I am reading in an xml document, and then I am able to access data like this:

def root = new XmlParser().parseText(xmlString)
println root.foo.bar.text()

What I would like to do, is to have loaded the "foo.bar" portion of the path from a file or data base, so that I can do something like this:

def paths = ["foo.bar","tashiStation.powerConverter"] // defined for this example
paths.each { 
    path ->
    println path + "\t" + root.path.text()
}

Obviously the code as written does not work... I thought maybe this would work:

paths.each { 
    path ->
    println path + "\t" + root."${path}".text()
}

...but it doesn't. I based my initial solution on pg 153 of Groovy for DSL where dynamic methods can be created in a similar way.

Thoughts? The ideal solution will not add significant amounts of code and will not add any additional library dependencies. I can always fall back to doing this stuff in Java with JDOM but I was hoping for an elegant groovy solution.

The McG
  • 175
  • 2
  • 14
  • possible duplicate of [Access object properties in groovy using \[\]](http://stackoverflow.com/questions/4077168/access-object-properties-in-groovy-using) – tim_yates Jul 16 '12 at 15:11
  • @tim_yates: doesn't look like the same thing to me at all... and inserting a call to the GroovyShell on every iteration would introduce unwanted overhead. – The McG Jul 16 '12 at 15:18
  • I can't see how that answer inserts a call to the GroovyShell – tim_yates Jul 16 '12 at 15:19
  • @tim_yates: the answer suggests using Eval and that is just a helper on top of GroovyShell right? – The McG Jul 16 '12 at 15:20
  • No, it first suggests what is shown below, then offers `Eval` as an alternative (obviously worse, as it -- as you correctly point out -- re-parses the property string to work out its value) – tim_yates Jul 16 '12 at 15:25
  • @tim_yates: you are absolutely right - accepted your answer. Thanks! – The McG Jul 16 '12 at 15:29

1 Answers1

3

This is very similar to this question from 3 days ago and this question

You basically need to split your path on . and then walk down this list moving through your object graph

def val = path.split( /\./ ).inject( root ) { obj, node -> obj?."$node" }?.text()
println "$path\t$val"

Should do it in this instance :-)

Community
  • 1
  • 1
tim_yates
  • 167,322
  • 27
  • 342
  • 338