I'm trying to construct a XML feed, and Groovy's MarkupBuilder is giving me headaches:
def newsstandFeed(def id) {
def publication = Publication.get(id)
def issues = issueService.getActiveIssuesForPublication(publication)
def updateDate = DateUtil.getRFC3339DateString(publication.lastIssueUpdate)
def writer = new StringWriter()
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
def xml = new MarkupBuilder(writer)
xml.feed('xmlns':"http://www.w3.org/2005/Atom", 'xmlns:news':"http://itunes.apple.com/2011/Newsstand") {
updated("${updateDate}")
issues.each { issue ->
entry {
id (issue.id)
updated("${DateUtil.getRFC3339DateString(issue.lastUpdated)}")
published("${DateUtil.getRFC3339DateString(issue.releaseDate)}")
summary(issue.summary)
"news:cover_art_icons" {
"news:cover_art_icon" (size:"SOURCE", src:"${issue.cover.remotePath}")
}
}
}
}
return writer.toString()
}
I get this exception:
Class groovy.lang.MissingMethodException
No signature of method: java.lang.String.call() is applicable for argument types: (org.codehaus.groovy.runtime.GStringImpl) values: [CYB_001] Possible solutions: wait(), any(), wait(long), any(groovy.lang.Closure), take(int), each(groovy.lang.Closure)
"CYB_001" is the first "id" attribute.
If I rename "id" it to "ids" or anything else, it works, and returns a proper XML document:
....
issues.each { issue ->
entry {
ids ("${issue.id}")
...
Any ideas why this is happening, and how I can work around the problem?
The environment is Grails 2.1.1 (so Groovy 1.8, I assume)
It seems to me that your XML builder is trying to reference some String variable in the environment. Since groovy builder intercept missing method calls, if they find a reference they will try to apply to it. The following code can reproduce your error:
def id = ""
new groovy.xml.MarkupBuilder().xml {
id "90"
}
And the following is fine:
def ids = ""
new groovy.xml.MarkupBuilder().xml {
id "90"
}
Renaming your id
variable should do the trick
Update:
An alternative way to use a tag with same name as a variable in the scope is with a (ugly) GString:
def id = ""
new groovy.xml.MarkupBuilder().xml {
"${'id'}" "90"
}