1

我有一个使用jaxb2-maven-plugin编译一些 xsd 文件的 Maven 项目。它使用staleFile 来确定是否有任何引用schemaFiles已更改。不幸的是,有问题的 xsd 文件使用标签来包含参数<xs:include schemaLocation="../relative/path.xsd"/>中未列出的其他模式文件,因此插件中的计算无法准确检测何时需要实际重新编译。随着包含的模式的发展,这最终会破坏增量构建。schemaFilestaleFile

显然,一种解决方案是在执行的schemaFile. 但是,在某些情况下,开发人员不这样做会破坏构建。相反,我想以某种方式自动生成此列表。

想到的一种方法是以某种方式解析顶级 XSD 文件,然后设置属性或输出文件,然后我可以将其传递给schemaFile参数或schemaFiles参数。Groovy gmaven 插件似乎是将功能直接嵌入到 POM 中的一种自然方式。但是我对 Groovy 还不够熟悉,无法入门。

谁能提供一些示例代码?或者提供替代实施/解决方案?

谢谢!

4

2 回答 2

1

根据 tim_yates 的回答,以下是一个可行的解决方案,您可能必须根据配置 jaxb2 插件的方式对其进行自定义。

在使用以下配置gmaven-plugin运行的生命周期早期(例如,在初始化阶段)配置执行...

从收集引用模式的 File 对象的函数开始(这是对 Tim 答案的改进):

def findRefs { f ->
    def relPaths = new XmlSlurper().parse(f).depthFirst().findAll {
        it.name()=='include'
    }*.@schemaLocation*.text()
    relPaths.collect { new File(f.absoluteFile.parent + "/" + it).canonicalFile }
}

将其包装在一个迭代结果的函数中,直到找到所有孩子:

def recursiveFindRefs = { schemaFiles ->
    def outputs = [] as Set
    def inputs  = schemaFiles as Queue
    // Breadth-first examine all refs in all schema files
    while (xsd = inputs.poll()) {
        outputs << xsd
        findRefs(xsd).each {
            if (!outputs.contains(it)) inputs.add(it)
        }
    }
    outputs
}

当您解析 Maven 项目以确定要做什么时,真正的魔力就出现了。首先,找到 JAXB 插件:

jaxb = project.build.plugins.find { it.artifactId == 'jaxb2-maven-plugin' }

然后,解析该插件的每次执行(如果您有多个)。该代码假定每个执行集schemaDirectory, schemaFilesand staleFile(即不使用默认值!)并且您没有使用schemaListFileName

jaxb.executions.each { ex ->
    log.info("Processing jaxb execution $ex")
    // Extract the schema locations; the configuration is an Xpp3Dom
    ex.configuration.children.each { conf ->
        switch (conf.name) {
            case "schemaDirectory":
                schemaDirectory = conf.value
                break
            case "schemaFiles":
                schemaFiles = conf.value.split(/,\s*/)
                break
            case "staleFile":
                staleFile = conf.value
                break
        }
    }

最后,我们可以打开 schemaFiles,使用我们之前定义的函数解析它们:

    def schemaHandles = schemaFiles.collect { new File("${project.basedir}/${schemaDirectory}", it) }
    def allSchemaHandles = recursiveFindRefs(schemaHandles)

...并将它们的最后修改时间与陈旧文件的修改时间进行比较,必要时取消链接陈旧文件。

    def maxLastModified = allSchemaHandles.collect {
            it.lastModified()
        }.max()
    def staleHandle = new File(staleFile)
    if (staleHandle.lastModified() < maxLastModified) {
        log.info("  New schemas detected; unlinking $staleFile.")
        staleHandle.delete()
    }
}
于 2011-02-28T19:00:28.750 回答
1

不确定如何将它集成到 Maven 构建中——Maven 不是我真正喜欢的 :-(

但是,如果您有xsd文件的路径,您应该能够通过执行以下操作来获取它引用的文件:

def rootXsd = new File( 'path/to/xsd' )
def refs = new XmlSlurper().parse( rootXsd ).depthFirst().findAll { it.name()=='include' }.@schemaLocation*.text()
println "$rootXsd references $refs"

字符串列表也是如此refs,它应该是包含的 xsds 的路径

于 2011-02-25T14:07:27.300 回答