eerohele / saxon-gradle

A Gradle plugin for running XSLT transformations with Saxon
MIT License
16 stars 6 forks source link

support transformation with no file source #11

Closed lionelmoi closed 5 years ago

lionelmoi commented 6 years ago

In the Saxon documentation: http://www.saxonica.com/html/documentation/using-xsl/commandline/

-it[:template-name] Selects the initial named template to be executed. If this is namespaced, it can be written as {uri}localname. If the template name is omitted, the default is xsl:initial-template. When this option is used, you do not need to supply a source file, but if you do, you must supply it using the -s option.

But if I do not specify an input the plugins fails with this error

FAILURE: Build failed with an exception.

* What went wrong:
path may not be null or empty string. path='null'

Stacktrace

java.lang.IllegalArgumentException: path may not be null or empty string. path='null'
        at org.gradle.api.internal.file.AbstractBaseDirFileResolver.doResolve(AbstractBaseDirFileResolver.java:65)
        at org.gradle.api.internal.file.AbstractFileResolver.resolve(AbstractFileResolver.java:86)
        at org.gradle.api.internal.file.AbstractFileResolver.resolve(AbstractFileResolver.java:68)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileCollectionConverter.convertInto(DefaultFileCollectionResolveContext.java:177)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:138)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileCollections(DefaultFileCollectionResolveContext.java:94)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileCollectionConverter.convertInto(DefaultFileCollectionResolveContext.java:161)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:111)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileCollections(DefaultFileCollectionResolveContext.java:94)
        at org.gradle.api.internal.file.CompositeFileCollection.getSourceCollections(CompositeFileCollection.java:172)
        at org.gradle.api.internal.file.CompositeFileCollection.getFiles(CompositeFileCollection.java:55)
        at org.gradle.api.internal.file.AbstractFileCollection.iterator(AbstractFileCollection.java:68)
        at com.github.eerohele.SaxonXsltTask.getOutputFiles(SaxonXsltTask.groovy:661)
        at com.github.eerohele.SaxonXsltTask_Decorated.getOutputFiles(Unknown Source)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
        at org.gradle.api.internal.project.taskfactory.TaskPropertyInfo$4.create(TaskPropertyInfo.java:99)
        at org.gradle.util.SingleMessageLogger.whileDisabled(SingleMessageLogger.java:228)
        at org.gradle.api.internal.project.taskfactory.TaskPropertyInfo.getValue(TaskPropertyInfo.java:97)
        at org.gradle.api.internal.project.taskfactory.TaskClassValidator$FutureValue.call(TaskClassValidator.java:71)
        at org.gradle.util.GUtil.uncheckedCall(GUtil.java:436)
        at org.gradle.util.DeferredUtil.unpack(DeferredUtil.java:37)
        at org.gradle.api.internal.tasks.CompositeTaskOutputPropertySpec.resolveToOutputProperties(CompositeTaskOutputPropertySpec.java:49)
        at org.gradle.api.internal.tasks.DefaultTaskOutputs$5.apply(DefaultTaskOutputs.java:197)
        at org.gradle.api.internal.tasks.DefaultTaskOutputs$5.apply(DefaultTaskOutputs.java:193)
        at com.google.common.collect.Iterators$8.transform(Iterators.java:794)
        at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:48)
        at com.google.common.collect.Iterators$5.hasNext(Iterators.java:543)
        at org.gradle.api.internal.tasks.TaskPropertyUtils.collectFileProperties(TaskPropertyUtils.java:34)
        at org.gradle.api.internal.tasks.DefaultTaskOutputs.getFileProperties(DefaultTaskOutputs.java:203)
        at org.gradle.api.internal.tasks.DefaultTaskOutputs$TaskOutputUnionFileCollection.visitContents(DefaultTaskOutputs.java:280)
        at org.gradle.api.internal.file.CompositeFileCollection.getSourceCollections(CompositeFileCollection.java:171)
        at org.gradle.api.internal.file.CompositeFileCollection.getFiles(CompositeFileCollection.java:55)
        at org.gradle.api.internal.file.AbstractFileCollection.iterator(AbstractFileCollection.java:68)
        at com.google.common.collect.Iterables$8.iterator(Iterables.java:713)
        at com.google.common.collect.Sets.newHashSet(Sets.java:219)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.canonicalizedPaths(DefaultTaskExecutionPlan.java:709)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.getOutputPaths(DefaultTaskExecutionPlan.java:785)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.recordTaskStarted(DefaultTaskExecutionPlan.java:815)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.access$2700(DefaultTaskExecutionPlan.java:91)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan$9.transform(DefaultTaskExecutionPlan.java:601)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan$9.transform(DefaultTaskExecutionPlan.java:590)
        at org.gradle.internal.resources.DefaultResourceLockCoordinationService.withStateLock(DefaultResourceLockCoordinationService.java:45)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.selectNextTask(DefaultTaskExecutionPlan.java:590)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.access$2300(DefaultTaskExecutionPlan.java:91)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan$8.transform(DefaultTaskExecutionPlan.java:564)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan$8.transform(DefaultTaskExecutionPlan.java:545)
        at org.gradle.internal.resources.DefaultResourceLockCoordinationService.withStateLock(DefaultResourceLockCoordinationService.java:45)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:545)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
eerohele commented 6 years ago

Yes, this is a clear oversight on my part. I'll look into it when I get the chance.

eerohele commented 6 years ago

v0.6.0 adds support for no-input transformations. Please give it a go and let me know whether it works for you.

lionelmoi commented 6 years ago

I encountered the following error

:namesDescs:xslt FAILED

FAILURE: Build failed with an exception.

* What went wrong:
A problem was found with the configuration of task ':namesDescs:xslt'.
> Cannot write to file 'C:\workspace\tds\tds_xsl\namesDescs\build' specified for property 'outputFiles' as it is a directory.

I get no error when I specify anb input file with 0.6.0

Might i be related to the typing here ?

in SaxonXsltTask.groovy

 @OutputFiles
    FileCollection getOutputFiles() {
        if (this.options.input != null) {
            project.files(this.options.input.collect { getOutputFile(it) })
        } else {
            project.files(this.options.output)
        }
    }

Stacktrace

* Exception is:
org.gradle.api.tasks.TaskValidationException: A problem was found with the configuration of task ':namesDescs:xslt'.
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:625)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:580)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: org.gradle.api.InvalidUserDataException: Cannot write to file 'C:\workspace\tds\tds_xsl\namesDescs\build' specified for property 'outputFiles' as it is a directory.
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:47)
        ... 24 more
eerohele commented 6 years ago

Hmm. I'm guessing you don't have the output option defined? Can you try defining that to point to a file (for example, ${buildDir}/output.xml)?

If you don't define an output file, the Saxon CLI prints the transformation result into stdout, but that doesn't make much sense for this plugin, so I think you'll need to define the output file.

If you set the input option, the plugin uses the input file name + the extension defined in the @method attribute of the <xsl:output> output element, but since in this case there's no input file, we can't infer the file name.

I think the options are to either modify the plugin to use a generic name (such as output.xml) or give a better error message.

lionelmoi commented 6 years ago

I also don't have a , I use since I oftten have more than one document to output.

I like the generic name option. I would add a message describing this behavior when no output is defined.

No ouput parameter, using output.xml as a default.

Or something like that.

eerohele commented 6 years ago

Right, sorry for the misleading comment — xslt:output isn't necessary, it's only used if it's there.

Does using output but no input work for you?

lionelmoi commented 6 years ago

It would make my life easier if I could just define a directory as an output. But I can work with having to define a "dummy" output.

eerohele commented 6 years ago

Saxon doesn't allow a no-input transformation that has a directory output:

$ saxon -xsl:xsl/no-input.xsl -it:initial-template -o:build
Output is a directory, but input is not
lionelmoi commented 6 years ago

Well that settles it ! I will define a dummy output then.

eerohele commented 6 years ago

I should document this in the newly opened wiki.