Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to call xml-maven-plugin by passing only the initial template to be executed? #62

Open
dandn opened this issue Jun 21, 2021 · 4 comments

Comments

@dandn
Copy link

dandn commented Jun 21, 2021

When using the Saxon-HE command line (currently version 10.5), one can make a call as follows: saxon -it -xsl:my-stylesheet.xsl -o:output.xml

For the command above, by default the template with name xsl:initial-template in the specified stylesheet is executed.
No file names are needed as input.

Questions:

  • Is there any way the xml-maven-plugin can be invoked similarly (using Saxon-HE as a dependency) by passing this -it parameter (or equivalent) and with no dir element in the related transformationSet?
  • Is there any way we can specify the output as a single file? Rather than an output dir - the outputDir in the related transformationSet.
@jochenw
Copy link
Member

jochenw commented Jun 22, 2021

I couldn't really tell. My assumption is, that such a "named template" is basically just a lookup into a map, where the template name is being mapped to a URI. So, if you know the URI, you can use that, and everything should work just fine. Apart from that, I am at a loss. (We are managing the xml-maven-plugin, not Saxon.)

If there should be some kind of standard mechanism, that I have missed in my 20 years of XML related work, I am ready to learn, and to extend the plugin, as far as the standard goes. I am drawing the line at Saxon specific stuff, though.

@dandn
Copy link
Author

dandn commented Jun 24, 2021

Thank you for the quick reply. Admittedly I am a novice when it comes to using XSLT.

I realise that the simple solution for my issue of not requiring an input file was to create an empty xml file as my source when calling my template.

I do see that XSLT 3.0 in section 2.3.4 does indicate that "a stylesheet may be evaluated by selecting a named template to be evaluated".

My current approach to calling the xsl:initial-template is to use xsl:call-template as follows:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">

    <xsl:template name="xsl:initial-template">
        ... code removed ...
    </xsl:template>

    <!-- Use the following until it's possible to directly call the xsl:initial-template above.
         As a workaround, call this template with a single empty file. -->
    <xsl:template match="/">
        <xsl:call-template name="xsl:initial-template"/>
    </xsl:template>

</xsl:stylesheet>

Perhaps you could provide an example of how I could include the URI approach above to specify a named template when using the xml-maven-plugin?

@dandn dandn closed this as completed Jun 24, 2021
@dandn dandn reopened this Jun 24, 2021
@bmix
Copy link

bmix commented Sep 19, 2021

The XSL Initial Template is a mechanism new to XSL-T 3.0. It is not a proprietary Saxon feature. From the XSL spec:

[Definition: A stylesheet may be evaluated by selecting a named template to be evaluated; this is referred to as the initial named template.] The effect is analogous to the effect of executing an xsl:call-template instruction. The following information is needed in this case:

Optionally, the name of the initial named template which is to be executed as the entry point to the transformation. If no template name is supplied, the default template name is xsl:initial-template. The selected template must exist within the stylesheet.
etc.

This is how Saxon implements it:

-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.

The right way to use it would be:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">

  <xsl:template name="xsl:initial-template">
    <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="whatever">
    <xsl:apply-templates />
  <xsl:template>

  and so on...

</xsl:stylesheet>

The "initial template" is the main entry point to the stylesheet and gets executed first. As we can see, it does not require an input-document, thus, and only in this case, the stylesheet can be called without an input XML file. The output gets created programmatically from the contents of the stylesheet.

@andreblanke
Copy link

I found this issue because I had a similar requirement of transforming XML files loaded from a directory using the collect function and merging them into a single output file afterward. Unless I am mistaken, this is currently not possible using the XML Maven Plugin, as the stylesheet of a transformationSet is applied once for each XML file in the specified dir, always producing n output files.

I wanted to share my approach for this for anyone else who might stumble upon this issue. The basic idea is to declare an (optional) dependency on Saxon

<dependencies>
  <dependency>
    <groupId>net.sf.saxon</groupId>
    <artifactId>Saxon-HE</artifactId>
    <version>12.3</version>
    <!-- Avoid a transitive dependency on Saxon. -->
    <optional>true</optional>
  </dependency>
</dependencies>

and to use the Exec Maven Plugin to invoke the Saxon CLI shipped with the library (which supports the XSL Initial Template mechanism):

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>3.1.0</version>
  <executions>
    <execution>
      <id>transform-xml</id>
      <phase>generate-resources</phase>
      <goals>
        <goal>java</goal>
      </goals>
      <configuration>
        <mainClass>net.sf.saxon.Transform</mainClass>
        <arguments>
          <argument>-it</argument>
          <argument>-xsl:${project.basedir}/stylesheet.xslt</argument>
          <argument>-o:${project.build.outputDirectory}/output.xml</argument>
        </arguments>
      </configuration>
    </execution>
  </executions>
</plugin>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants