我正在使用Groovy的StreamingMarkupBuilder根据一些SQL查询的结果动态生成XML。我想从闭包内部调用一个方法,但标记构建器尝试使用方法名称创建一个XML节点。
以下是我正在尝试做的一个例子:
Map generateMapFromRow(GroovyRowResult row) {
def map = [:]
def meta = row.getMetaData()
// Dynamically generate the keys and values
(1..meta.getColumnCount()).each { column -> map[meta.getColumnName(column)] = row[column-1] }
return map
}
def sql = Sql.newInstance(db.url, db.user, db.password, db.driver)
def builder = new StreamingMarkupBuilder()
def studentsImport = {
students {
sql.eachRow('select first_name, middle_name, last_name from students') { row ->
def map = generateMapFromRow(row) // Here is the problem line
student(map)
}
}
}
println builder.bind(studentsImport).toString()
这将生成类似于以下内容的XML:
<students>
<generateMapFromRow>
[first_name:Ima, middle_name:Good, last_name:Student]
</generateMapFromRow>
<student/>
<generateMapFromRow>
[first_name:Ima, middle_name:Bad, last_name:Student]
</generateMapFromRow>
<student/>
</students>
我已经尝试将方法移到类中并静态调用类,这也不起作用。
由于StreamingMarkupBuilder的工作原理,我担心实际上不可能这样做,但我希望它是。
答案 0 :(得分:1)
在示例简化期间,我可能会松散,但这样的代码可以正常工作。
在你的例子中,学生是一个闭包调用,所以它可能会混乱。
def builder = new groovy.xml.StreamingMarkupBuilder()
def generateMapFromRow = { ["$it": it] }
builder.bind {
10.times {
def map = generateMapFromRow(it) // Now closure is escaped, there is local variable with such name.
student(map)
}
}
如上所述:http://groovy.codehaus.org/Using+MarkupBuilder+for+Agile+XML+creation
使用标记构建器时要注意的事项不是要重叠当前在范围内的变量。以下是一个很好的例子
import groovy.xml.MarkupBuilder
def book = "MyBook"
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.shelf() {
book(name:"Fight Club") { // Will produce error.
}
}
println writer.toString()
Builder的工作类似于MethodMissing绑定器,如果范围内有局部变量,则不会产生任何节点。