json-doc('http://example.com/foo.json') not supported when running xslt3 from the command line?
Added by Martin Honnen over 4 years ago
When I run an XSLT 3 stylesheet using e.g. json-doc('http://example.com/foo.json')
from the command line with e.g. xslt3 -it -xsl:sheet.xsl
, like
<?xml version="1.0" encoding="utf-8"?>
<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="adaptive"/>
<xsl:template name="xsl:initial-template">
<xsl:sequence
select="json-doc('https://raw.githubusercontent.com/martin-honnen/martin-honnen.github.io/master/xslt/2020/test2020061801.json')"/>
</xsl:template>
</xsl:stylesheet>
I get an error saying
Transformation failure: Error FOUT1170 at json-doc-test1.xsl#11
Cannot read file https://raw.githubusercontent.com/martin-honnen/martin-honnen.github.io/master/xslt/2020/test2020061801.json - Synchronous access to non-file resources is not allowed
Transformation failed: Error FOUT1170 at json-doc-test1.xsl#11
Cannot read file https://raw.githubusercontent.com/martin-honnen/martin-honnen.github.io/master/xslt/2020/test2020061801.json - Synchronous access to non-file resources is not allowed
There is some text in the documentation (last paragraph in http://saxonica.com/saxon-js/documentation/index.html#!development/asynchrony) saying that with Node synchronous access to resources over HTTP(S) is not allowed.
Is there some way to run xslt3
in a asynchronous way or some other way to have access over HTTP(S) for json-doc
supported?
Replies (3)
Please register to reply
RE: json-doc('http://example.com/foo.json') not supported when running xslt3 from the command line? - Added by Michael Kay over 4 years ago
Good question.
With the SaxonJS.transform() API, there are two ways to achieve asynchronous access to JSON documents.
The first way is to pre-load the document using SaxonJS.getResource()
, which returns a promise, and only execute the transformation when this promise is resolved. The parsed document can either be passed in as a stylesheet parameter, or it can be placed directly (but only as unparsed text) in the document pool, where fn:json-doc()
will find it.
The second way is to use ixsl:schedule-action
with a document
attribute whose value is a URI ending in ".json". This will cause the scheduled action to fire when the document is available, and again a call on fn:json-doc() will find the document in the pool.
From the command line, only the second option is available. Prefetching a document e.g. using ?in="json-doc('http://..../')"
won't work, unfortunately, because the XPath evaluation is synchronous.
For access to HTTP resources in Node.js we're using the axios library, which only provides asynchronous interfaces. (In the browser we use XmlHttpRequest
, which has the option of synchronous operation, though it's highly deprecated.) We can't call an asynchronous function in the middle of evaluating an XPath expression, we can only do it under very controlled circumstances (we plan to make improvements in this area, but there will still be restrictions). It would certainly be possible to extend the command line to do some of the asynchronous pre-fetching that can be done in the API using getResource(), but (a) the syntax might get a bit clumsy, and (b) pre-fetching, of course, doesn't work for applications where the URI is obtained dynamically.
RE: json-doc('http://example.com/foo.json') not supported when running xslt3 from the command line? - Added by Martin Honnen over 4 years ago
I have tried the approach with ixsl:schedule-action
, unfortunately it generates an error I can't explain:
Transformation failed: TypeError: c.codePointAt is not a function
The sample XSLT is
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT"
exclude-result-prefixes="#all">
<xsl:output method="adaptive"/>
<xsl:param name="url" as="xs:string">https://swapi.dev/api/people/</xsl:param>
<xsl:template name="xsl:initial-template">
<ixsl:schedule-action document="{$url}">
<xsl:call-template name="output-json">
<xsl:with-param name="url" select="$url"/>
</xsl:call-template>
</ixsl:schedule-action>
</xsl:template>
<xsl:template name="output-json">
<xsl:param name="url" select="$url"/>
<xsl:variable name="json-doc1" select="json-doc($url)"/>
<xsl:result-document href="json-doc-test-with-schedule-action-5.json" method="json" indent="yes">
<xsl:sequence select="$json-doc1"/>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
Full error is
PS C:\Users\marti\SomeDir> xslt3 -t -it -xsl:.\json-doc-test-with-schedule-action-5.xsl
Saxon-JS 2.0 from Saxonica
Node.js version v12.18.0
Compiling stylesheet C:\Users\marti\SomeDir\json-doc-test-with-schedule-action-5.xsl
Stylesheet compilation time: 0.16s
Initial template: Q{http://www.w3.org/1999/XSL/Transform}initial-template
SEF generated by Saxon-JS 2.0 at 2020-06-19T17:36:56.263+02:00 with -target:JS -relocate:true
Transformation failed: TypeError: c.codePointAt is not a function
RE: json-doc('http://example.com/foo.json') not supported when running xslt3 from the command line? - Added by Michael Kay over 4 years ago
Raised as bug #4608, please track it there.
Please register to reply