Project

Profile

Help

Should fn:transform always return a map with an "output" property or can it return an empty map if the principal result is empty?

Added by Martin Honnen 4 months ago

I am wondering why I get an empty map from fn:transform if the principal result is empty, I would nevertheless expect the map to have a property named output with an empty string result.

I am getting different results using fn:transform, depending on whether I use 'delivery-format' : 'raw' or 'delivery-format' : 'serialized', in the latter case I am getting an empty map with no output property.

Testing using Saxon HE 12.4:

File 1:

declare namespace output = 'http://www.w3.org/2010/xslt-xquery-serialization';

declare option output:method 'adaptive';

transform(
  map {
    'delivery-format' : 'raw',
    'source-node' : document { <root>test</root> },
    'stylesheet-node' : <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">

  <xsl:output method="text"/>

  <xsl:template match="/" name="xsl:initial-template">
    <xsl:for-each-group select="foo/bar" group-by="baz">
      <group count="{{count(current-group())}}"/>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>
  }
)

Output:

map{"output":()}

File 2:

declare namespace output = 'http://www.w3.org/2010/xslt-xquery-serialization';

declare option output:method 'adaptive';

transform(
  map {
    'delivery-format' : 'serialized',
    'source-node' : document { <root>test</root> },
    'stylesheet-node' : <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">

  <xsl:output method="text"/>

  <xsl:template match="/" name="xsl:initial-template">
    <xsl:for-each-group select="foo/bar" group-by="baz">
      <group count="{{count(current-group())}}"/>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>
  }
)

Output:

map{}


Replies (2)

RE: Should fn:transform always return a map with an "output" property or can it return an empty map if the principal result is empty? - Added by Michael Kay 4 months ago

Interesting question.

The spec does say:

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.

But the XSLT 3.0 spec also says:

In previous versions of this specification it was stated that when the raw result of the initial template or function is an empty sequence, a result tree should be produced if and only if the transformation generates no secondary results (that is, if it does not invoke xsl:result-document). This provision is most likely to have a noticeable effect if the transformation produces serialized results, and these results are written to persistent storage: the effect is then that a transformation producing an empty principal result will overwrite any existing content at the base output URI location if and only if the transformation produces no other output. Processor APIs offering backwards compatibility with earlier versions of XSLT must respect this behavior, but there is no requirement for new processor APIs to do so.

So there's some deliberate ambiguity about what XSLT delivers by way of serialized output if the principal result is empty, and this presumably carries over into fn:transform.

RE: Should fn:transform always return a map with an "output" property or can it return an empty map if the principal result is empty? - Added by Martin Honnen 4 months ago

I see.

For the time being I fixed the JavaScript frontend of my SaxonC 12 Python powered XML workbench https://saxonc-xmlworkbench.azurewebsites.net/ which uses fn:transform to run XSLT to handle the case when fn:transform returns an empty map and therefore JavaScript receives no result documents (if there have been no secondary result documents) from the Python REST API.

    (1-2/2)

    Please register to reply