Inline output document selection using result document in XSLT 2.0
Question
Greetings,
I'm looking for a method to do in-line result (output) document selecting in XSLT. I know of the method where one creates an xsl:result-document
node to have one transformation apply to multiple documents. Usually this method uses several passes, such as:
<xsl:template match="/">
<xsl:apply-templates select="*"/>
<xsl:result-document href="test.xml">
<xsl:apply-templates select="*"/>
</xsl:result-document>
</xsl:template>
I'm looking for a way to do this inline so I can build two output documents in a single pass. The reason is I have a temporary tree that is built as the transformation is run that I want to output to a file.
<xsl:variable name="treeBase">
<Base/>
</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="these_elements">
<xsl:param name="temp" select="$treeBase"/>
</xsl:template>
<xsl:template match="not_these_elements">
<xsl:param name="temp" select="$treeBase"/>
<xsl:apply-templates select="@*|node()">
<xsl:with-param name="temp">
<Base>
<xsl:copy-of select="$temp/Base/*"/>
<Item>
<xsl:value-of select="ThisItem"/>
</Item>
</Base>
</xsl:with-param>
</xsl:template>
Why would you want to do this? In my XSLT I'm building a temporary tree through recursive parameter calls. I want to output the temporary tree as it is being built to a separate document but still use the temporary tree built for flow of control. With the current method I'd have to run through a complex transformation twice.
Is there a way to do this in XSLT or is it single-pass, single-document only?
Thanks in advance.
Solution
Here is a working example how to do this:
This transformation:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<!-- -->
<xsl:template match="/*">
<xsl:variable name="vTop" select="."/>
<!-- -->
<xsl:for-each-group select="num" group-by="xs:integer(.) mod 2">
<xsl:result-document href="file:///C:/Temp/file{position()}.xml">
<xsl:element name="{name($vTop)}">
<xsl:copy-of select="current-group()"/>
</xsl:element>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>010</num>
</nums>
produces the wanted two files: file1.xml and file2.xml, which contain, correspondingly, the "num" elements with odd and with even values.
Do note that there are no "multiplr passes" and the code is "inline", as required.