xsltsaxonxslt-3.0saxon-js

Unknown function saxon:parse-html when compiling stylesheet


I am working on an XSL transformation on Oxygen using the Saxon-EE 10.3 transformer. I want to use the compiled stylesheet (sef.json) later on my website with Saxon-JS 2. Inside of the XSL transformation I am using the saxon:parse-html function with the saxon namespace declared as following:

<xsl:stylesheet xmlns:prop="http://saxonica.com/ns/html-property"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
    xmlns:style="http://saxonica.com/ns/html-style-property" 
    xmlns:saxon="http://saxon.sf.net/"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT"
    xmlns:js="http://saxonica.com/ns/globalJS" 
    exclude-result-prefixes="xs prop ixsl js style saxon xhtml"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="3.0"
    xpath-default-namespace="http://www.tei-c.org/ns/1.0" 
    xmlns="http://www.tei-c.org/ns/1.0">

and the function is called this way:

          <xsl:call-template name="nameTemplate">
              <xsl:with-param name="html">
                  <xsl:copy-of select="saxon:parse-html(var)"></xsl:copy-of>
              </xsl:with-param>
          </xsl:call-template>

I tried to compile the stylesheet through this command:

xslt3 -xsl:test.xsl -export:test.sef.json -t

but I encounter the following error:

Failed to compile stylesheet: Static error in XPath on line 147 in Oxygen/Test.xsl {saxon:parse-html(?Text)}: Unknown function Q{http://saxon.sf.net/}parse-html()
Error Q{http://www.w3.org/2005/xqt-errors}XPST0017 at xpath.xsl#963
    Failed to compile stylesheet
Error Q{http://www.w3.org/2005/xqt-errors}XPST0017 at xpath.xsl#963
    Static error in XPath on line 147 in Oxygen/Test.xsl {saxon:parse-html(?Text)}: Unknown function Q{http://saxon.sf.net/}parse-html()

The transformation works without problem inside Oxygen though.


Solution

  • You might need to call into JavaScript e.g. set up a script element

    <script>
    function parseHTML(html) { return new DOMParser().parseFromString(html, 'text/html'); }
    </script>
    

    in your HTML document and then inside of XSLT with Saxon JS 2 in the browser you should be able to use e.g.

    ixsl:window() => ixsl:get('parseHTML') => ixsl:apply([var])
    

    instead of saxon:parse-html(var), with a namespace declaration of xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT" in your XSLT.

    Another way to not require you to set up the script code in addition to the XSLT code is to use ixsl:eval to run the JavaScript directly from XSLT in Saxon-JS 2; I have set up an example at https://martin-honnen.github.io/saxon-js-parse-html-test/html/test-saxon-parse-html2.html which basically uses an implementation

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="3.0"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:saxon="http://saxon.sf.net/"
      xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT"
      exclude-result-prefixes="#all"
      expand-text="yes">
    
      <xsl:function name="saxon:parse-html" as="document-node()" use-when="system-property('xsl:product-name') = 'Saxon-JS'">
        <xsl:param name="html" as="xs:string"/>
        <xsl:sequence select="ixsl:eval('new DOMParser()') => ixsl:call('parseFromString', [$html, 'text/html'])"/>
      </xsl:function>
    
    </xsl:stylesheet>
    

    of the XSLT 3 module https://github.com/martin-honnen/saxon-js-parse-html-test/blob/master/xslt/override-saxon-parse-html2.xsl.

    You can xsl:import that in your other XSLT code, as done in https://github.com/martin-honnen/saxon-js-parse-html-test/blob/master/xslt/test-override-saxon-parse.xsl with e.g. <xsl:import href="override-saxon-parse-html2.xsl"/> and call e.g. saxon:parse-html(.).

    I managed to compile that code to an SEF file with the settings xslt3 -xsl:test-override-saxon-parse.xsl -nogo -export:test-override-saxon-parse. -sef.json -ns:"##html5" and that way the HTML page https://martin-honnen.github.io/saxon-js-parse-html-test/html/test-saxon-parse-html2.html can simply run that XSLT with

               SaxonJS.transform({
                    stylesheetLocation: '../xslt/test-override-saxon-parse.sef.json',
                    sourceLocation: '../xml/sample2.xml',
                    destination: 'appendToBody'
                }, 'async')
    

    As an alternative, you could import the pure XSLT 2 HTML parser that David Carlisle has somewhere on GitHub into your XSLT code.