Project

Profile

Help

json-doc('http://example.com/foo.json') not supported when running xslt3 from the command line?

Added by Martin Honnen about 2 months 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 about 2 months 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 about 2 months 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
    (1-3/3)

    Please register to reply