1

I'm trying to use a groovy Config entry to parse an xml file with XmlSlurper.

Here's the Config file:

sample {
    xml {
        frompath = "Email.From"
    }
}

Here's the XML

<xml>
    <Email>
        <From>
            <Address>foo@bar.com</Address>
            <Alias>Foo Bar</Alias>
        </From>
    <Email>
</xml>

This is what I tried initially:

XmlSlurper slurper = new XmlSlurper()

def record = slurper.parseText((new File("myfile.xml")).text)

def emailFrom = record?."${grailsApplication.config.sample.xml.frompath}".Address.text()

This doesn't work because XmlSlurper allows one to use special characters in path names as long as they're surrounded by quotes, so the app is translating this as:

def emailFrom = record?."Email.From".Address.text()

and not

def emailFrom = record?.Email.From.Address.text()

I tried setting the frompath property to be "Email"."From" and then '"Email"."From"'. I tried tokenizing the property in the middle of the parse statement (don't ask.)

Can someone please point me towards some resources to find out if/how I can do this?

I feel like this issue getting dynamic Config parameter in Grails taglib and this https://softnoise.wordpress.com/2013/07/29/grails-injecting-config-parameters/ may have whispers of a solution, but I need fresh eyes to see it.

Community
  • 1
  • 1
Jaye
  • 184
  • 8

1 Answers1

1

The solution in issue getting dynamic Config parameter in Grails taglib is a proper way to deref down such a path. E.g.

def emailFrom = 'Email.From'.tokenize('.').inject(record){ r,it -> r."$it" }
def emailFromAddress = emailFrom.Address.text()

If your path there can get complex and you rather go with the potentially more dangerous way, you could also use Eval. E.g.

def path = "a[0].b.c"
def map = [a:[[b:[c:666]]]] // dummy map, same as xmlslurper
assert Eval.x(map, "x.$path") == 666
Community
  • 1
  • 1
cfrick
  • 35,203
  • 6
  • 56
  • 68
  • Ah, thanks. I thought injection would figure into it. I updated the example, is it possible for you help me with that second level? – Jaye Jan 27 '15 at 16:47
  • to apply above code for your example you would pass `record` instead of `map`. the path should be obvious. the result from the inject would be `record.Email.From` then and from there you can add your `Address.text()` (if that is a given). otherwise i might have misunderstood your problem. – cfrick Jan 27 '15 at 16:53
  • NO! I was being dim and missing what the end object would be - I printed out path after the injection and couldn't figure out why it was just my split Config property. This works, thanks for your time! – Jaye Jan 27 '15 at 16:59