You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Groovy编写的Gradle插件中计算XML定义的Ant Fileset

在Gradle插件中用Groovy解析XML里的Ant Fileset

其实这个需求实现起来挺顺畅的——毕竟Gradle天生就和Ant深度集成,Groovy处理XML又灵活得不行。下面给你一套最简的实现方案,分步骤来:

1. 用XmlSlurper解析XML文件

首先你需要把包含Fileset的XML文档读进来,用Groovy的XmlSlurper来解析,它能通过GPath表达式轻松定位到目标节点。假设你的XML结构大概是这样:

<config>
  <fileset dir="src/main/java" includes="**/*.java" excludes="**/test/**">
    <include name="**/utils/**"/>
    <exclude name="**/deprecated/**"/>
  </fileset>
</config>

那解析代码可以这么写:

def xmlFile = project.file('path/to/your/config.xml') // 用Gradle的file方法获取文件实例
def config = new XmlSlurper().parse(xmlFile)
def filesetNodes = config.fileset // 直接定位所有fileset节点

2. 把XML节点映射到Ant Fileset并计算匹配文件

Gradle的project.ant对象直接提供了Ant任务的调用能力,我们可以把XML里的Fileset属性、子节点一一映射到Ant的fileset任务上,然后就能拿到匹配的文件列表了。

基础版(处理简单属性和直接子节点)

filesetNodes.each { filesetNode ->
    // 初始化Ant Fileset,先传入dir、includes、excludes这些顶层属性
    def antFileset = project.ant.fileset(
        dir: filesetNode.@dir.text(),
        includes: filesetNode.@includes.text(),
        excludes: filesetNode.@excludes.text()
    )

    // 处理子节点里的<include>和<exclude>
    filesetNode.include.each { include ->
        antFileset.include(name: include.@name.text())
    }
    filesetNode.exclude.each { exclude ->
        antFileset.exclude(name: exclude.@name.text())
    }

    // 把Ant返回的文件转换成Gradle的File对象集合
    def matchedFiles = antFileset.files.collect { new File(it.absolutePath) }
    // 这里就可以对文件做自定义操作了,比如打印、传给其他任务
    println "匹配到的文件:${matchedFiles.size()}个"
    matchedFiles.each { println it.name }
}

进阶版(处理嵌套的patternset)

如果你的XML里有嵌套的<patternset>节点,也能轻松处理:

filesetNodes.each { filesetNode ->
    def antFileset = project.ant.fileset(dir: filesetNode.@dir.text())

    // 处理根节点的includes/excludes属性
    if (filesetNode.@includes.text()) {
        antFileset.includes = filesetNode.@includes.text()
    }
    if (filesetNode.@excludes.text()) {
        antFileset.excludes = filesetNode.@excludes.text()
    }

    // 处理直接的include/exclude子节点
    filesetNode.include.each { antFileset.include(name: it.@name.text()) }
    filesetNode.exclude.each { antFileset.exclude(name: it.@name.text()) }

    // 处理嵌套的patternset
    filesetNode.patternset.each { patternset ->
        patternset.include.each { antFileset.include(name: it.@name.text()) }
        patternset.exclude.each { antFileset.exclude(name: it.@name.text()) }
        // 也支持patternset本身的includes/excludes属性
        if (patternset.@includes.text()) {
            antFileset.includes += ",${patternset.@includes.text()}"
        }
        if (patternset.@excludes.text()) {
            antFileset.excludes += ",${patternset.@excludes.text()}"
        }
    }

    def matchedFiles = antFileset.files.collect { new File(it.absolutePath) }
    // 后续自定义逻辑...
}

3. 集成到Gradle插件中

如果是写Gradle插件,你可以把这段逻辑封装到自定义Task里,比如:

class ProcessXmlFilesetTask extends DefaultTask {
    @InputFile
    File configXml

    @TaskAction
    void processFileset() {
        def config = new XmlSlurper().parse(configXml)
        def filesetNodes = config.fileset

        filesetNodes.each { filesetNode ->
            def antFileset = project.ant.fileset(dir: filesetNode.@dir.text())
            // 这里添加上面的属性和子节点处理逻辑...
            def matchedFiles = antFileset.files.collect { new File(it.absolutePath) }
            project.logger.lifecycle("从XML Fileset匹配到 ${matchedFiles.size()} 个文件")
        }
    }
}

// 在插件里注册任务
void apply(Project project) {
    project.tasks.register('processXmlFileset', ProcessXmlFilesetTask) {
        configXml = project.file('config.xml')
    }
}

这套方案完全利用了Groovy的XML处理能力和Gradle对Ant的内置支持,代码简洁还能完美复用XML里的Fileset定义。

内容的提问来源于stack exchange,提问作者Jörn Guy Süß

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:06:10