I have three xsl files and one input file:
-input.xml process1.xsl output1.xml
-output1.xml process2.xsl output3.xml
now i want to just have it as:
input.xml process.xslt output.xml
process1.xsl, process2.xsl and their outputs should passed as the
input to the xsl file and generate output.xml in the same process.xsl file.
how do i do this in xslt , i have referred to xslt apply imports but i am not getting proper reference for assigning the xml output as input for another xsl file all in one xsl.. can anyone help me out?
here i have invoked the input.xml and used process1.xsl for first step
and the output generated is stored in the $content variable now i am stuck here that how do i import the process2.xsl and assing it to the previous output in variable $content, i am just able to display its output i want to assing it to next xsl file:
<xsl:import href="process1.xsl"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="content">
<xsl:apply-imports/>
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($content)/*" mode="m"/>
</xsl:template>
<xsl:template match="@*|*|text()" mode="m">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="@*|*|text()" mode="m"/>
</xsl:copy>
</xsl:template>
something like this but this does not work?
Using XSLT 3.0 you could use the fold-left
function (https://www.w3.org/TR/xpath-functions-31/#func-fold-left) together with the transform
function (https://www.w3.org/TR/xpath-functions-31/#func-transform) to chain the transformations:
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
exclude-result-prefixes="fn xs">
<xsl:param name="sheet-uris" as="xs:string*" select="'process1.xsl', 'process2.xsl'"/>
<xsl:param name="input-uri" as="xs:string" select="'input.xml'"/>
<xsl:param name="input-doc" as="document-node()" select="doc($input-uri)"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template name="xsl:initial-template">
<xsl:apply-templates select="fold-left($sheet-uris, $input-doc, function($input, $sheet-uri) { transform(map { 'stylesheet-location' : $sheet-uri, 'source-node' : $input })?output })"/>
</xsl:template>
<xsl:template match="/*">
<xsl:comment select="'Processed by ' || document-uri(document(''))"/>
<xsl:next-match/>
</xsl:template>
</xsl:stylesheet>
Obviously in a real transformation your stylesheet would do more than outputting a comment to indicate its processing the input but using above stylesheet called with Saxon 9.7 EE and -it -xsl:process.xsl
, where the input is
<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>bar</foo>
</root>
and the two stylesheets process1.xsl
and process2.xsl
are for instance
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xhtml="http://www.w3.org/1999/xhtml" exclude-result-prefixes="array fn map math xhtml xs">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="/*">
<xsl:comment select="'Processed by ' || document-uri(document(''))"/>
<xsl:next-match/>
</xsl:template>
</xsl:stylesheet>
the output is
<?xml version="1.0" encoding="UTF-8"?><!--Processed by file:/SomePath/process1.xsl--><!--Processed by file:/SomePath/process2.xsl--><!--Processed by file:/SomePath/process.xsl--><root>
<foo>bar</foo>
</root>
so the chaining is working.
Instead of passing the input document as a parameter you could also provide it as the primary input -s
and change the main stylesheet to
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
exclude-result-prefixes="fn xs">
<xsl:param name="sheet-uris" as="xs:string*" select="'process1.xsl', 'process2.xsl'"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="/">
<xsl:apply-templates select="fold-left($sheet-uris, ., function($input, $sheet-uri) { transform(map { 'stylesheet-location' : $sheet-uri, 'source-node' : $input })?output })/node()"/>
</xsl:template>
<xsl:template match="/*">
<xsl:comment select="'Processed by ' || document-uri(document(''))"/>
<xsl:next-match/>
</xsl:template>
</xsl:stylesheet>
If you want to chain transformations with Java then see https://stackoverflow.com/a/35845231/252228 for an example.