Locating the result document after fn:transform()

Something unexpected happened when I ran an XSLT transformation using fn:transform() within another XSLT script, instead of just running it directly.

<xsl:variable name="xslt-options" as="map(*)">
  <xsl:map>
    <xsl:map-entry key="'stylesheet-location'" select="$url"/>
    <xsl:map-entry key="'source-node'" select="$input"/>
    <xsl:map-entry key="'stylesheet-params'" select="$stylesheet-params"/>
  </xsl:map>
</xsl:variable>

<xsl:variable name="output" as="map(*)" select="fn:transform($xslt-options)"/>

<xsl:sequence select="map:get($output,'output')"/>

My stylesheet located at $url uses <xsl:result-document> to produce some secondary output, but it's no longer written to a file.

Why?

Buried in the W3C XPath 3.1 recommendation is the following:

The result of the transformation is returned as a map. There is one entry in the map for the principal result document, and one for each secondary result document.

Oh, OK then. The map that is returned by fn:transform() doesn't just contain the main result under the key output, it also contains the items generated by <xsl:result-document>, each under a key that is the @href value of <xsl:result-document>.

So now I produce the full set of output:

<xsl:for-each select="map:keys($output)">
  <xsl:choose>
    <xsl:when test=". = 'output'">
      <xsl:sequence select="map:get($output,.)"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:result-document href="{.}">
        <xsl:sequence select="map:get($output,.)"/>
      </xsl:result-document>
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each>

(Other formulations are available.)

Published
Categorised as XSLT