Project

Profile

Help

Bug #5079

closed

resolve-uri doesn't take static-base-uri of included module into account, even with relocate:off Saxon EE compiled/exported XSLT

Added by Martin Honnen about 1 year ago. Updated 5 months ago.

Status:
Closed
Priority:
Low
Category:
XSLT Conformance
Sprint/Milestone:
-
Start date:
2021-09-03
Due date:
% Done:

100%

Estimated time:
Applies to JS Branch:
2, Trunk
Fix Committed on JS Branch:
2, Trunk
Fixed in JS Release:
SEF Generated with:
Platforms:
Company:
-
Contact person:
-
Additional contact persons:
-

Description

I learned today that using the option -relocate:off when exporting an XSLT stylesheet having included or imported modules is the key to "preserve" the static base URI of each module as otherwise the static-base-uri() is simply the URI of the complete SEF file.

When testing with Saxon JS 2 (2.3, both under Node.js as in the browser), however, I found that exporting from EE for Saxon-JS with -relocate:off ensures that Saxon-JS has a different static-base-uri() for templates from different modules but that resolve-uri($relative-uri) doesn't seem to take that static base URI into account for included modules.

So running e.g.

<?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:import href="xslt/inner-base-uri-test1.xsl"/>
    
    <xsl:output indent="yes"/>
    
    <xsl:mode on-no-match="shallow-copy"/> 
    
    <xsl:template match="uri">
        <xsl:copy>
            <xsl:attribute name="static-base-uri" select="static-base-uri()"/>
            <xsl:attribute name="base-uri" select="base-uri()"/>
            <xsl:attribute name="resolve-uri" select="resolve-uri(.)"/>
            <xsl:apply-templates/>
        </xsl:copy>
        <xsl:next-match/>
    </xsl:template>
    
</xsl:stylesheet>

where the inner-base-uri-test1.xsl in the subdir is e.g.

<?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 match="uri">
        <xsl:comment>nested stylesheet module</xsl:comment>
        <xsl:copy>
            <xsl:attribute name="static-base-uri" select="static-base-uri()"/>
            <xsl:attribute name="base-uri" select="base-uri()"/>
            <xsl:attribute name="resolve-uri" select="resolve-uri(.)"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

against an XML sample like

<?xml version="1.0" encoding="UTF-8"?>
<uris>
    <uri>foo.xml</uri>
    <uri>../foo.xml</uri>
    <uri>../../foo.xml</uri>
</uris>

shows that the static-base-uri() result is different in the included module from the subdirectory but the resolve-uri(.) call for the main stylesheet's template and the included one's gives the same result:

<?xml version="1.0" encoding="UTF-8"?>
<uris>
   <uri static-base-uri="file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/resolve-uri-test/compiler/base-uri-test1.xsl" base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml" resolve-uri="https://martin-honnen.github.io/xslt/2021/includes/foo.xml">foo.xml</uri>
   <!--nested stylesheet module--><uri static-base-uri="file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/resolve-uri-test/compiler/xslt/inner-base-uri-test1.xsl" base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml" resolve-uri="https://martin-honnen.github.io/xslt/2021/includes/foo.xml">foo.xml</uri>
   <uri static-base-uri="file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/resolve-uri-test/compiler/base-uri-test1.xsl" base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml" resolve-uri="https://martin-honnen.github.io/xslt/2021/foo.xml">../foo.xml</uri>
   <!--nested stylesheet module--><uri static-base-uri="file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/resolve-uri-test/compiler/xslt/inner-base-uri-test1.xsl" base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml" resolve-uri="https://martin-honnen.github.io/xslt/2021/foo.xml">../foo.xml</uri>
   <uri static-base-uri="file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/resolve-uri-test/compiler/base-uri-test1.xsl" base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml" resolve-uri="https://martin-honnen.github.io/xslt/foo.xml">../../foo.xml</uri>
   <!--nested stylesheet module--><uri static-base-uri="file:/C:/Users/marti/OneDrive/Documents/xslt/blog-xslt-3-by-example/resolve-uri-test/compiler/xslt/inner-base-uri-test1.xsl" base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml" resolve-uri="https://martin-honnen.github.io/xslt/foo.xml">../../foo.xml</uri>
</uris>

https://martin-honnen.github.io/xslt/2021/resolve-uri-test1.html is the online, client-side Saxon-JS 2.3 test case.

The result that Saxon-Java gives is showing differences for the resolve-uri(.) calls based on whether it is done in the template of the main stylesheet or the included module e.g.

<?xml version="1.0" encoding="UTF-8"?>
<uris>
   <uri static-base-uri="https://martin-honnen.github.io/xslt/2021/includes/base-uri-test1.xsl"
        base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml"
        resolve-uri="https://martin-honnen.github.io/xslt/2021/includes/foo.xml">foo.xml</uri>
   <!--nested stylesheet module-->
   <uri static-base-uri="https://martin-honnen.github.io/xslt/2021/includes/xslt/inner-base-uri-test1.xsl"
        base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml"
        resolve-uri="https://martin-honnen.github.io/xslt/2021/includes/xslt/foo.xml">foo.xml</uri>
   <uri static-base-uri="https://martin-honnen.github.io/xslt/2021/includes/base-uri-test1.xsl"
        base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml"
        resolve-uri="https://martin-honnen.github.io/xslt/2021/foo.xml">../foo.xml</uri>
   <!--nested stylesheet module-->
   <uri static-base-uri="https://martin-honnen.github.io/xslt/2021/includes/xslt/inner-base-uri-test1.xsl"
        base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml"
        resolve-uri="https://martin-honnen.github.io/xslt/2021/includes/foo.xml">../foo.xml</uri>
   <uri static-base-uri="https://martin-honnen.github.io/xslt/2021/includes/base-uri-test1.xsl"
        base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml"
        resolve-uri="https://martin-honnen.github.io/xslt/foo.xml">../../foo.xml</uri>
   <!--nested stylesheet module-->
   <uri static-base-uri="https://martin-honnen.github.io/xslt/2021/includes/xslt/inner-base-uri-test1.xsl"
        base-uri="https://martin-honnen.github.io/xslt/2021/sample-uris1.xml"
        resolve-uri="https://martin-honnen.github.io/xslt/2021/foo.xml">../../foo.xml</uri>
</uris>

So it seems Saxon-JS 2.3 has a bug in resolve-uri, not taking the static-base-uri into account, even when running an exported SEF/JSON file that was exported with -relocate:off.


Files

sample-uris1.xml (132 Bytes) sample-uris1.xml Martin Honnen, 2021-09-03 20:47
base-uri-test1.xsl (745 Bytes) base-uri-test1.xsl Martin Honnen, 2021-09-03 20:48
base-uri-test1.xsl-relocate-off.sef.json (3.41 KB) base-uri-test1.xsl-relocate-off.sef.json Martin Honnen, 2021-09-03 20:48
inner-base-uri-test1.xsl (634 Bytes) inner-base-uri-test1.xsl Needs to be in xslt subdirectory Martin Honnen, 2021-09-03 20:48
Actions #1

Updated by Debbie Lockett 5 months ago

  • Status changed from New to In Progress
  • Assignee set to Debbie Lockett

Thanks for reporting this and supplying the example; and apologies for the fact that it has been ignored for so long!

I've reproduced the bug, and I'm working on fixing this.

What is happening is that when -relocate:off is used, the results for the static-base-uri() calls have actually been calculated at compile time; whereas the calls on resolve-uri() resolve against a static base URI calculated at run time - and there is a bug in the SaxonJS code here. Apparently the internal context.fixed.staticBaseURI value is initialized (e.g. using the transform options stylesheetBaseURI, stylesheetLocation or stylesheetFileName) when we first initialize the context, even for relocatable SEFs, which shouldn't happen (because in relocatable SEFs, the static base URI can vary when there are different modules).

Relatedly, this work has reminded me that we don't provide the -relocate command line option for the XX compiler (i.e. with the SaxonJS command line xslt3 package). All XX-compiled SEFs are relocatable. But it would be useful to provide this option - I'll add a separate issue for this (see Feature #5462: Add "-relocate" command line option for XX compiler (xslt3 package)).

Actions #2

Updated by Debbie Lockett 5 months ago

  • Status changed from In Progress to Resolved
  • Applies to JS Branch Trunk added
  • Fix Committed on JS Branch 2, Trunk added

Unit tests added: for Node.js (nodejs/iss5079) and browser (browser/iss5079 and iss5079NR), testing results of resolve-uri() against static base URI for both relocatable and non-relocatable SEFs.

Fix committed in transform.js to check whether the SEFs are relocatable before initializing context.fixed.staticBaseURI. (Property "isRelocatableStylesheet" is added to the internal transform options, and initialized when we first prime an SEF.)

Fix committed to saxonjs2 and main branches.

Actions #3

Updated by Debbie Lockett 5 months ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in JS Release set to SaxonJS 2.4

Bug fix applied in the SaxonJS 2.4 maintenance release.

Please register to edit this issue

Also available in: Atom PDF Tracking page