Project

Profile

Help

Why is Saxon-JS trying to access the XSL when everything is in the SEF file ?

Added by Jang Graat over 2 years ago

I am integrating Saxon-JS in an application running on an eXist-db server.

Running a simple transform (a single template in the original XSL) works fine, but with a more elaborate styleheet, Saxon-JS apparently tries to load the XSL from which the SEF was compiled. That code is not available at the expected URL, as the compile to SEF is done from oXygen and the exist-db handle from oXygen becomes part of the URL. Obviously, when viewing pages from the http handler of eXist, this URL does not resolve due to cross-origin access restrictions (and it would probably not have worked anyway).

This is a complete knock-out for using Saxon-JS in real projects, as I cannot rely on the original XSL being available at a fixed location (if any) on the client's web server. What I need to understand is why access to the original XSL is needed at all, and if that is not needed, then how do I tell Saxon-JS to not try and load the XSL?

Many thanks for a quick response.

4everJang


Replies (6)

Please register to reply

RE: Why is Saxon-JS trying to access the XSL when everything is in the SEF file ? - Added by John Lumley over 2 years ago

A possibility is where the code executes @document(@ $uri @)@ where $uri has been bound to the empty string ''. In this case the standard says that the URI is resolved against the static base URI, which will usually be that of the original XSL, and hence it requests the original XSLT stylesheet. This technique was often used in 1.0 to read tables defined in the stylesheet. It might be that you're using a legacy stylesheet that employs this technique.

Saxon-JS will implement this action according to the standard.

RE: Why is Saxon-JS trying to access the XSL when everything is in the SEF file ? - Added by Jang Graat over 2 years ago

Thanks, John, but that is not what is happening in my XSL.

I dug into the error message a little more and it turns out that the SaxonJS code is trying to access the original file when reporting on an error. That does not seem to be part of the standard to me. If there is a way to avoid this behavior that would be good, as an error message should not itself cause a fatal error.

Kind regards

Jang

RE: Why is Saxon-JS trying to access the XSL when everything is in the SEF file ? - Added by John Lumley over 2 years ago

Could you give us some more details:

  • A stack trace
  • What the error being trapped is - the XSL code causing it
  • How you are trapping the error - usually Saxon-JS.transform() will throw an XError for external catching, unless you're using xsl:try/xsl:catch internally
  • Most usefully, a minimal example that does this that we can run
  • Snapshots from your 'dig into the error message'

RE: Why is Saxon-JS trying to access the XSL when everything is in the SEF file ? - Added by Jang Graat over 2 years ago

Hello John,

Thanks for your quick reply.

Unfortunately. things are quite complicated in this project, which is why it is not easy to give you a simple example that will reproduce the problem on your end. Let me try to explain the issue:

I am running eXist-db 4.0 which is creating HTML pages from a number of XLIFF, XML and HTML files in its database, using XQuery. As all the code, as well as all assets used by the generated HTML pages, is stored in the eXist-db, the oXygen editor uses its own eXist-db database handler to access the XSLT. This means that the URL from oXygen's viewpoint starts with "oxygen:/exist-db localhost$exist-db-4.0/db". I am using oXygen to compile the XSL to SEF and then import the SEF into the eXist-db so that it can be referenced from the JS code that is also pulled from the database by the browser. From the browser's viewpoint, every resource URL starts with "localhost:7080/exist/rest/db". This is the mismatch that causes fatal errors in the browser, as cross-origin access is denied. Even though everything runs from my localhost, the URLs do appear to come from different servers.

I tried to manually edit the references in the SEF, but that causes a checksum error on the file, as could have been expected. So I am really stuck between a rock and a hard place. As I do need to meet my deadline for this project, I decided to ditch SaxonJS for now and recreate the entire transform in XQuery. I tried running the transform in eXist, but that is unbearably slow, for reasons I do not even want to investigate.

In my view, the above cross-origin problem is something more or less generic that should be handled in the error reporting mechanism used by SaxonJS. Accessing the original XSL to report on errors is a very nice feature, but as we are working in a world that puts up fences to avoid abuse of browser technology, this type of issue will undoubtedly pop up in more projects than just mine.

Kind regards

Jang

RE: Why is Saxon-JS trying to access the XSL when everything is in the SEF file ? - Added by Michael Kay over 2 years ago

Adding to John's response: By default, the static base URI of the transformation is still the original location of the XSL file. However, this can be changed by setting relocate:on when generating the SEF file.

The XSLT 3.0 spec says in §5.3.1:

Static base URI: In a conventional interpreted environment, the static base URI of an expression in the stylesheet is the base URI of the containing element in the stylesheet. The concept of the base URI of a node is defined in Section 5.2 base-uri Accessor DM30. When stylesheets are executed in an environment where no source code is present (for example, because the code of the stylesheet has been compiled and is distributed as executable object code), it is recommended (subject to operational constraints such as security) that the static base URI used during stylesheet evaluation should be the location from which the stylesheet was loaded for execution (its “deployed location”). This means, for example, that when the docFO30 or document functions are called with a relative URI, the required document is by default located relative to the deployed location of the stylesheet.

We got these rules into the spec (there are similar statements in XPath/XQuery) specifically to handle the kind of situation encountered by Saxon-JS; however, there is still a tendency for the specs to assume that source code is available at execution time.

The static base URI is used as a default base URI for functions that access resources, e,g, doc, document, unparsed-text, json-doc. You should either give these an absolute URI to work with (obtained perhaps by calling resolve-uri() to resolve against the location of the HTML page), or if you're going to default to static-base-uri(), make sure you set relocate:on so this is the location of the SEF file rather than the source XSLT.

Note that the common XSLT 1.0 trick of using document('') with an empty URI to access the source XSLT shouldn't be used with Saxon-JS.

I don't think your theory that Saxon is accessing the source file during error reporting is correct. At any rate, if this is happening, it's not by design, so we need to see more details in order to reproduce the effect.

RE: Why is Saxon-JS trying to access the XSL when everything is in the SEF file ? - Added by Jang Graat over 2 years ago

Thanks, Michael, for the info about handling static base URIs. I will try wo work this option after I have met the deadline for the current project. I am still a fan of using XSLT in the browser, even though the combination with an eXist-db as the web server complicates things a bit. I will certainly be revisiting SaxonJS in future projects that are based on a hosted PHP environment.

Kind regards

Jang

    (1-6/6)

    Please register to reply