使用新的 'file' 节点在 Gradle/Groovy 中操作 XML

Manipulating XML in Gradle/Groovy with new 'file' node

我正在尝试操纵 wildfly 10.1。 standalone.xml 通过 gradle buildscript 修改记录器设置。我以前做过这个,并且使用记录器条目,这按预期工作。但是,现在我需要添加一个新的 periodic-rotating-file-handler,这本身不是问题,但在尝试告诉实际登录到哪个文件时它确实起作用了。

现有代码:

def configFile = {wildflyDir}/standalone/configuration/standalone.xml"
def xml = new XmlSlurper(false,false).parse(configFile)
def logging = xml.profile.subsystem.find{ it['@xmlns'] == "urn:jboss:domain:logging:3.0' }
logging.appendNode {
    logger(category:"loggingCategory") {
        level(name:"LEVEL")
    }
}

正如预期的那样,这是非常实用的。现在我需要添加这样的片段:

<periodic-rotating-file-handler>
    <formatter>
        <named-formatter name="PATTERN" />
    </formatter>
    <file path="file.log" relative-to="jboss.logging.dir" />
    <suffix value=".yyyy-MM-dd" />
    <append value="true" />
</periodic-rotating-file-handler>

file 定义中存在问题,因为 build.gradle 文件中的定义如下所示:

file(path:"file.log" "relative-to":"jboss.logging.dir")

这被 gradle 解释为 new File(arg1, arg2),所以基本上它试图将具有给定参数的文件对象添加到 XML.

这是有效的,但绝对不是我想要的,因为我只需要相应的 XML 节点。我尝试了多种逃脱方式:

还有一些我尝试过的东西,但由于沮丧我想不起来了。

我最后的尝试是尝试向 XML 添加一个空的 file 节点,但是当使用 file() 时 gradle 不知道哪个文件构造器使用,当我使用 file 时出现错误:Namespace prefix: file is not bound to a URI

如果有人知道如何正确转义 file 或者有其他方法可以将所述 file-node 添加到 XML,请告诉我。

谢谢。

(1) 在委托上调用生成器函数:

//just declare `file` to emulate problem in usual groovy console 
def file={String a, String b-> println "file: a=$a, b=$b"}

def xml = new XmlSlurper(false,false).parseText('''
    <root>
        <profile>
            <subsystem xmlns="urn:jboss:domain:logging:3.0"/>
        </profile>
    </root>''')

def logging = xml.profile.subsystem.find{ it['@xmlns'] == "urn:jboss:domain:logging:3.0" }

logging.plus{
    logger(category:"loggingCategory") {
        level(name:"LEVEL")
    }
    //be specific that you want to call file function on delegate and not on owner (by default)
    delegate.'file'(path:"file.log", "relative-to":"jboss.logging.dir")
    //or this also works:
    "${'file'}"(path:"file.log", "relative-to":"jboss.logging.dir")

}

println groovy.xml.XmlUtil.serialize(xml)

(2) 使用 XmlParser 的解决方法:

使用current作为当前父节点的访问者

def xml = new XmlParser(false,false).parseText('''
    <root>
        <profile>
            <subsystem xmlns="urn:jboss:domain:logging:3.0"/>
        </profile>
    </root>''')

def logging = xml.profile.subsystem.find{ it['@xmlns'] == "urn:jboss:domain:logging:3.0" }

logging.plus{
    logger(category:"loggingCategory") {
        level(name:"LEVEL")
    }
    current.appendNode("file", [path:"file.log", "relative-to":"jboss.logging.dir"])
}

println groovy.xml.XmlUtil.serialize(xml)