saxon-gradle 0.10.1
I’ve completely reworked my Saxon Gradle plugin. Feedback solicited.
A couple of years ago, I forkedI’ve “unforked” it now because I can’t practically imagine the new version could provide any useful or interesting feedback to the original project. Eero Helenius’s saxon-gradle project to fix some issues that arose in my workflow. This was one of my first attempts at a Gradle plugin and I learned a lot from Eero’s project.
Some of my ideas were good, some were bad. Eero was very patient. Time passed.
I felt like I’d left it languishing for a while and I really ought to try to wrap it up. My initial thought was to revisit the project and go all-in on integrating Saxon into Gradle. I was going to try to expose all of the Saxon APIs natively in Gradle.
Except, no. That would be an enormous amount of work and 99% of it would probably never be used. Would it be cool to implement a module URI resolver in Groovy and use it in Saxon running in Gradle? Maybe. But would it be useful in any practical sense? Probably not.
There’s a fair bit of complexity in setting up the configuration. I’d have to basically reimplement everything that the command line argument parser already does. And that would invariably introduce version dependencies between Saxon and the plugin.
Then I thought about going in the other direction. Could I write a
plugin that has no dependency on Saxon? The secret sauce that the
plugin uses is the fact that you can instantiate a Transformer
, call doTransform(args)
,
and Saxon will do exactly what it would have done if you’d called the
main task and passed args
as the command line arguments.
I decided to strip the plugin back to its bare essentials. Eero’s
plugin provides a user-friendly DSL for all of the options it knows
about. You can specify settings for lineNumbers
and
messageReceiver
, for example. I decided instead to simply expose a
DSL that lets you pass in the arguments like you would on the command
line.
This means you have to specify the -l
and -m
options, arguably
less friendly, but it also means that the plugin will work without any
changes if some future version of Saxon introduces new options.
Another benefitThe Transform
or Query
objects necessary to run Saxon are
constructed with the Java reflection API, so thare are no explicit
dependencies. This also means you have to include some version of
Saxon in your build script. It won’t be pulled in as a dependency by
the plugin. is that the plugin will use exactly the version of
Saxon that you want to use in your Gradle script. You don’t have to
worry about version mismatches between your build and the plugin.
Looking around at the ways that I’ve actually wanted to use Saxon in Gradle, I decided to add a few new features as well.
-
It’s now possible to run XQuery transformations in addition to XSLT transformations. (There are some limitations in Saxon 11 that will be fixed in the next maintenance release.)
-
It’s possible to request that the transformation be performed in a separate Java process. This means you can run transforms with different Java properties or environment variables, or with a different classpath.
-
The process for examining XML documents and stylesheets to work out if they have additional dependencies has been ported to stylesheets that you can override if you have more specific requirements.
Note that Gradle does this during the configuration phase, so it will happen for every task that uses the feature, on every run, irrespective of what tasks actually get run. Useful, but perhaps best used sparingly.
These changes appeared in version 0.10.x of my plugin. I pushed a small fix this afternoon, so we’re up to version 0.10.1 now.
I’d love a bit of positive (or negative) feedback before I push this as 1.0.0.