Re: [xsl] How Best to Generate Result Documents from Nested Structures?

Subject: Re: [xsl] How Best to Generate Result Documents from Nested Structures?
From: "Abel Braaksma (Exselt) abel@xxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 2 Jun 2014 16:03:59 -0000
On 25-5-2014 19:50, Eliot Kimber ekimber@xxxxxxxxxxxx wrote:
> I think I misstated or misunderstood the restriction. The restriction I'm
> referring to is:
>
> "There are restrictions on the use of the xsl:result-document
> <http://www.w3.org/TR/xslt20/#element-result-document> instruction,
> designed to ensure that the results are fully interoperable even when
> processors optimize the sequence in which instructions are evaluated.
> Informally, the restriction is that the xsl:result-document
> <http://www.w3.org/TR/xslt20/#element-result-document> instruction can
> only be used while writing a final result tree, not while writing to a
> temporary tree or a sequence."
>
> From the XSLT 2 spec, 19.1 Creating Final Result Trees
>
> If I understand this statement it means that I can have nested
> xsl:result-document instructions if I'm otherwise generating the final
> result tree but not if I'm constructing an intermediate tree, meaning
> generation the value of a variable.

It is a bit more subtle than that. Some instructions, like xsl:function
and, as you already mentioned, xsl:variable or xsl:param, _always_
evaluate instructions in a temporary output state. In XSLT 2.0,
instructions such as xsl:attribute and xsl:comment are also in this list
(but not xsl:element), in XSLT 3.0, this restriction was dropped: all
node-creation instructions are in final output state, unless its calling
instruction is not.

> So given the document:
>
> <a>
>   <b>
>    <c/>
>   </b>
> </a>
>
> I should be able to do this:
>
> <xsl:template match="*">
>   <xsl:result-document href="{name(.)}.xml">
>     <result><xsl:value-of select="name(.)"/></result>
>     <xsl:apply-templates/>
>   </xsl:result-document>
> </xsl:template>
>
> And get three result documents, a.xml, b.xml, and c.xml.

The answer is, it depends. If this is your only template, then yes. But
if you expand your code as follows:

<xsl:template match="test">
    <xsl:value-of select="f:test(.)" />
</xsl:template>

<xsl:function name="f:test">
    <xsl:param name="foo" />
    <xsl:apply-templates select="$foo"  />
</xsl:function>

then it will fail, because the xsl:apply-templates inside xsl:function
will match your xsl:template, which has a child xsl:result-document.
Because xsl:function operates in a temporary output state and is
consider the "calling instruction" after an element "test" is matched,
it will throw error XTDE1480 (but only if the new template is actually
matched, otherwise, your stylesheet may run for a long time without
failing).

The reason this restriction exists is that an optimizing processor will
process a constructs like a variable or a function with a given argument
only once. Even if that were not the case, what would happen if you call
the function or variable from inside a pattern?

Cheers,

Abel Braaksma
Exselt XSLT 3.0 streaming processor
http://exselt.net

Current Thread