创建xml时是否可以使用闭包?我想用一个表示站点菜单的groovy对象创建一个xml。我正在使用StreamingMarkupBuilder并且正在努力让它使用闭包(我想要递归调用),但到目前为止还没有成功。
我正在创建这样的XML:
public menuToXml(Menu menu, def countrySpecificConfiguration) {
def builder = new StreamingMarkupBuilder()
builder.encoding = 'UTF-8'
def outputFile = builder.bind {
mkp.xmlDeclaration()
namespaces << ['']
siteMenu {
menu.menuItems.each menuItemToXml
}
}
}
我正在使用的封闭是:
def menuItemToXml = { menuItem ->
item {
logicalName(menuItem.name)
controller(menuItem.controller)
action(menuItem.action)
enabled(menuItem.enabled.toString())
pageID(menuItem.pageID)
mustBeLoggedIn(menuItem.mustBeLoggedIn.toString())
authorizedUserRoles {
menuItem.authorizedUserRoles.each { user -> userRole(user) }
}
childItems { menuItem.childItems.each menuItemToXml }
}
}
它一直给出以下错误(在“item {”行):
groovy.lang.MissingMethodException: No signature of method: com.ingim.flexiblecontent.service.DynamicMenuService.item() is applicable for argument types: (com.ingim.flexiblecontent.service.DynamicMenuService$_closure1_closure6) values: [com.ingim.flexiblecontent.service.DynamicMenuService$_closure1_closure6@aee1f98]
Possible solutions: use([Ljava.lang.Object;), is(java.lang.Object), grep(java.lang.Object), with(groovy.lang.Closure), wait(), every()
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:54)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
at com.ingim.flexiblecontent.service.DynamicMenuService$_closure1.doCall(DynamicMenuService.groovy:85)
.....
你能使用封闭装置,还是不可能?
包含闭包和调用方法的整个类:
package com.ingim.flexiblecontent.service
import groovy.xml.*
import com.ingim.flexiblecontent.Menu
class DynamicMenuService {
static transactional = false // not doing any transactions
static scope = "session" // one menu per user session
private Menu menu
/**
* Method to update the XML with the changes from the Menu.
*
*/
public menuToXml(Menu menu, def countrySpecificConfiguration) {
def builder = new StreamingMarkupBuilder()
builder.encoding = 'UTF-8'
def outputFile = builder.bind {
mkp.xmlDeclaration()
namespaces << ['']
siteMenu {
menu.menuItems.each {
println it.dump().toString()
menuItemToXml it
}
}
}
println XmlUtil.serialize(outputFile)
}
/**
* Closure to create XML from a menu item. Through recursive call creates child menu item(s) if present
* This can be multiple levels deep.
*
* @param menuItem the current menuItem
*
* @return the created XML
*/
def menuItemToXml = { menuItem ->
item {
logicalName(menuItem.name)
controller(menuItem.controller)
action(menuItem.action)
enabled(menuItem.enabled.toString())
pageID(menuItem.pageID)
mustBeLoggedIn(menuItem.mustBeLoggedIn.toString())
authorizedUserRoles {
menuItem.authorizedUserRoles.each { user -> userRole(user) }
}
childItems { menuItem.childItems.each menuItemToXml }
}
}
}
我正在使用的其他常规课程:
package com.ingim.flexiblecontent
class Menu {
def menuItems = []
def currentMenuItem // for storing the current menu item
public setMenuItems(def menuItems) {
this.menuItems = menuItems
}
}
和
package com.ingim.flexiblecontent
public class MenuItem {
String name
String controller
String action
boolean enabled
String pageID
boolean mustBeLoggedIn
def authorizedUserRoles = []
def childItems = [] //list of menu items
}
我正在使用以下方法进行测试:
void testMenuToXml() {
def menuService = new DynamicMenuService()
def menu = new Menu(menuItems: [
new MenuItem(name: 'menuItem1', controller: 'controller1', action: 'action1', enabled: true, pageID: '1', mustBeLoggedIn: true, authorizedUserRoles: ['role1', 'role2']),
new MenuItem(name: 'menuItem2', controller: 'controller2', action: 'action2', enabled: true, pageID: '2', mustBeLoggedIn: false, authorizedUserRoles: ['role1', 'role2'], childItems: [
new MenuItem(name: 'menuItem2a', controller: 'controller2a', action: 'action2a', enabled: true, pageID: '3', mustBeLoggedIn: true, authorizedUserRoles: ['role1']),
new MenuItem(name: 'menuItem2b', controller: 'controller2b', action: 'action2b', enabled: true, pageID: '4', mustBeLoggedIn: false, authorizedUserRoles: ['role2'])
])
])
def xml = '''<?xml version="1.0" encoding="UTF-8"?>
<countrySpecificConfiguration>
<country>BE</country>
<supportedLanguages>
<language>NL</language>
<language>FR</language>
</supportedLanguages>
<siteMenu>
<item>
</item>
</siteMenu>
</countrySpecificConfiguration>'''
def config = new XmlSlurper().parseText(xml)
menuService.menuToXml(menu, config)
}
答案 0 :(得分:0)
这有用吗?
menu.menuItems.each { menuItemToXml it }
而不是:
menu.menuItems.each menuItemToXml
很难说它是否适用于您的情况,因为您没有提供运行失败示例所需的所有信息......
答案 1 :(得分:0)
所以我可能会感到困惑,但我不认为你可以在你的“menuItemToXml”闭包中使用DSL。 builder.bind方法允许您使用DSL,但不能在您自己的闭包中使用。 因此,请尝试将所有{和}更改为地图符号[:]
即。 :item {---&gt;&gt;&gt;项目:[