Project

Profile

Help

Bug #6302

open

Saxon (HE; Java) trace not well-formed when XSLT uses transform function

Added by A Galtman 4 months ago. Updated 4 months ago.

Status:
New
Priority:
Low
Assignee:
-
Category:
-
Sprint/Milestone:
-
Start date:
2023-12-21
Due date:
% Done:

0%

Estimated time:
Legacy ID:
Applies to branch:
Fix Committed on Branch:
Fixed in Maintenance Release:
Platforms:

Description

(I alluded to this in my 12/21/23 comment in https://saxonica.plan.io/issues/6295 but it seems different enough that I'm making a separate issue for it rather than assume that the fix for 6295 is enough.)

The transform() function seems to cause the Saxon trace not to be well-formed.

Sample XSLT 1, transform-function.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:my="my-ns"
  exclude-result-prefixes="#all"
  version="3.0">

  <xsl:template name="xsl:initial-template">
    <xsl:variable name="transform-options" as="map(xs:string, item()*)">
      <xsl:map>
        <xsl:map-entry key="'delivery-format'" select="'raw'"/>
        <xsl:map-entry key="'stylesheet-location'">target-stylesheet-small.xsl</xsl:map-entry>
        <xsl:map-entry key="'function-params'" select="[()]"/>
        <xsl:map-entry key="'initial-function'" select="QName('my-ns', 'my:fcn')"/>
      </xsl:map>
    </xsl:variable>
    <xsl:sequence select="transform($transform-options)?output"/>
  </xsl:template>
</xsl:stylesheet>

Sample XSLT 2, target-stylesheet-small.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 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:my="my-ns"
  exclude-result-prefixes="#all"
  version="3.0">
  
  <xsl:function name="my:fcn" visibility="public" as="xs:string">
    <xsl:param name="p" as="empty-sequence()"/>
    <xsl:sequence select="'output'"/>
  </xsl:function>
  
</xsl:stylesheet>

Saxon command

java -cp "%SAXON_CP%" net.sf.saxon.Transform -opt:0 -T -Tlevel:high -it -xsl:transform-function.xsl 2>transform-function-traceresult.xml

I'm using Saxon-HE 12.4.

Trace Result

<trace saxon-version="12.4" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template name="xsl:initial-template" line="9" column="45" module="transform-function.xsl">
  <xsl:variable name="transform-options" line="10" column="73" module="transform-function.xsl">
   <trace text="target-stylesheet-small.xsl" line="13" column="52" module="transform-function.xsl">
   </trace>
<trace saxon-version="12.4" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:function arity="1" name="my:fcn" line="9" column="66" module="target-stylesheet-small.xsl">
    </xsl:function>
   </xsl:variable>
  </xsl:template>
</trace>
Actions #1

Updated by A Galtman 4 months ago

If I do something similar by making transform() call a template instead of a function, I do not see this problem.

Parent stylesheet that calls transform()

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  version="3.0">
  
  <xsl:template name="xsl:initial-template">
    <xsl:variable name="transform-options" as="map(xs:string, item()*)">
      <xsl:map>
        <xsl:map-entry key="'delivery-format'" select="'raw'"/>
        <xsl:map-entry key="'stylesheet-location'">target-stylesheet-template.xsl</xsl:map-entry>
        <xsl:map-entry key="'source-node'"><x/></xsl:map-entry>
        <xsl:map-entry key="'initial-template'" select="QName('', 'template-to-call')"/>
      </xsl:map>
    </xsl:variable>
    <xsl:sequence select="transform($transform-options)?output"/>
  </xsl:template>
  
</xsl:stylesheet>

target-stylesheet-template.xsl containing named template

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  version="3.0">
  
  <xsl:template name="template-to-call">
    <xsl:sequence select="'output'"/>
  </xsl:template>
  
</xsl:stylesheet>

Well-formed trace result

<trace saxon-version="12.4" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template name="xsl:initial-template" line="8" column="45" module="parent-stylesheet-template.xsl">
  <xsl:variable name="transform-options" line="9" column="73" module="parent-stylesheet-template.xsl">
   <trace text="target-stylesheet-template.xsl" line="12" column="52" module="parent-stylesheet-template.xsl">
   </trace>
   <trace name="x" line="13" column="48" module="parent-stylesheet-template.xsl">
   </trace>
<trace saxon-version="12.4" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template name="template-to-call" line="7" column="41" module="target-stylesheet-template.xsl">
    </xsl:template>
</trace>
  </xsl:variable>
 </xsl:template>
</trace>
Actions #2

Updated by Michael Kay 4 months ago

Yes, I'm aware that the trace output is "pseudo-XML". There are cases I know about where namespace prefixes aren't declared. It would probably be a good idea to push the output through a proper serializer, but I've been a bit reluctant because the serializer is likely to do some buffering and it's important not to lose anything if the transformation terminates abruptly.

Actions #3

Updated by A Galtman 4 months ago

The issue I'm seeing is about a "trace" start tag without a matching end tag. I just wanted to point that out in case it isn't part of what you're already aware of.

Actions #4

Updated by Michael Kay 4 months ago

For the missing trace end tag, I think I would need a repro. There are two possible causes: either the transformation is somehow being run using an API method that fails to write the end tag (and I can't find such a path), or the end tag is being written but not flushed to the output destination.

More generally, I think guaranteeing well-formed output from the trace is going to be a bit of a challenge. The most obvious case where we (apparently) make no attempt currently to achieve this is with try/catch. The other cases that are difficult are where the stylesheet uses multi-threading. Generally the combination of tracing and multi-threading is not going to produce comprehensible output, so the only options are (a) to disallow it, or (b) to produce output that is going to be hard to interpret (and probably ill-formed).

Actions #5

Updated by A Galtman 4 months ago

For the missing trace end tag, I think I would need a repro.

The "Sample XSLT 1, transform-function.xsl", "Sample XSLT 2, target-stylesheet-small.xsl", and "Saxon Command" sections of this issue writeup don't enable you to reproduce the problem with Saxon-HE 12.4? In case platform matters, I am using Windows. If there's other information I should provide, let me know.

Thanks for the observations about try/catch and multi-threading. Though they're not related to my specific reproduction steps here, they're useful to know. Anytime the trace isn't well-formed will be a situation where the code coverage feature in XSpec won't work, and maybe the XSpec documentation should describe limitations on the code coverage feature. So, if you think of any other situations where the trace from Saxon won't be well-formed or won't be accurate, I'd appreciate knowing the information.

Actions #6

Updated by Michael Kay 4 months ago

I'm wondering whether code coverage shouldn't be using a completely different trace listener, which rather than trying to produce a sequential execution trace as output, maintains a histogram of which instructions have been executed how many times? Rather like the TimingTraceListener (-TP option), in fact, but without the timings?

Please register to edit this issue

Also available in: Atom PDF