Project

Profile

Help

Should support for parse-html be detectable with e.g. use-when="function-available('parse-html')"?

Added by Martin Honnen over 1 year ago

Saxon 12 in PE and EE Java and with XSLT 4.0 and --enableSyntaxExtensions:on and with the right htmlparser jar on the class path supports the parse-html function but if the jar is not there or the version is not 4.0 and syntax extensions is not enabled the function is not supported. Nor it is supported in HE. SaxonCS 12 (as always being EE and incorporating AngleSharp) does support the function with XSLT 4.0 and syntax extension enabled.

Now I was wondering how to write XSLT code that gracefully checks whether the function is supported and hoped I could do that with e.g. use-when="function-available('parse-html')".

However, that doesn't seem to work.

I have the code

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="4.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:param name="html-fragment" as="xs:string" expand-text="no"><![CDATA[<p>This is paragraph 1.<p>This is paragraph 2 line 1.<br>This is paragraph 2 line 2.]]></xsl:param>

  <xsl:output method="xhtml" indent="yes" html-version="5"/>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template name="xsl:initial-template">
    <section>
      <h2>parse-html test</h2>
      <section>
         <h3>result</h3>
         <xsl:apply-templates select="parse-html($html-fragment)" use-when="function-available('parse-html')"/>
         <xsl:text use-when="not(function-available('parse-html'))">Couldn't parse HTML {$html-fragment}</xsl:text>
      </section>
    </section>
  </xsl:template>

  <xsl:template match="/">
    <xsl:next-match/>
    <xsl:comment>Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
  </xsl:template>

</xsl:stylesheet>

and run it with 'C:\Program Files\Saxonica\SaxonCS-12.0\SaxonCS.exe' transform -it -xsl:.\saxon-parse-html-test2.xsl --allowSyntaxExtensions:on but then it outputs e.g.

<?xml version="1.0" encoding="UTF-8"?><section>
   <h2>parse-html test</h2>
   <section>
      <h3>result</h3>Couldn't parse HTML &lt;p&gt;This is paragraph 1.&lt;p&gt;This is paragraph 2 line 1.&lt;br&gt;This is paragraph 2 line
      2.</section>
</section>

If I drop the use-when test and the xsl:text as in e.g.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="4.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:param name="html-fragment" as="xs:string" expand-text="no"><![CDATA[<p>This is paragraph 1.<p>This is paragraph 2 line 1.<br>This is paragraph 2 line 2.]]></xsl:param>

  <xsl:output method="xhtml" indent="yes" html-version="5"/>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template name="xsl:initial-template">
    <section>
      <h2>parse-html test</h2>
      <section>
         <h3>result</h3>
         <xsl:apply-templates select="parse-html($html-fragment)"/>
      </section>
    </section>
  </xsl:template>

  <xsl:template match="/">
    <xsl:next-match/>
    <xsl:comment>Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
  </xsl:template>

</xsl:stylesheet>

and run that with e.g. 'C:\Program Files\Saxonica\SaxonCS-12.0\SaxonCS.exe' transform -it -xsl:.\saxon-parse-html-test3.xsl --allowSyntaxExtensions:on however the function is used and I get e.g.

<?xml version="1.0" encoding="UTF-8"?><section>
   <h2>parse-html test</h2>
   <section>
      <h3>result</h3>
      <html xmlns="http://www.w3.org/1999/xhtml">
         <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
         </head>
         <body>
            <p>This is paragraph 1.</p>
            <p>This is paragraph 2 line 1.<br/>This is paragraph 2 line 2.</p>
         </body>
      </html>
      <!--Run with SAXON EE 12.0 --></section>
</section>

Why does the use-when="function-available('parse-html')" not work? What would be a better way to check the function is supported and available (I also played with try/catch but it seems e.g. in HE 12 it is a static and not a dynamic error that it doesn't have (fn:)parse-html so try/catch doesn't help).


Replies (2)

RE: Should support for parse-html be detectable with e.g. use-when="function-available('parse-html')"? - Added by Martin Honnen over 1 year ago

The only way I have found so far is using <xsl:when test="function-available('parse-html')" version="1.0">... use parse-html here</xsl:when> e.g.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="4.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  expand-text="yes"
  exclude-result-prefixes="#all">

  <xsl:param name="html-fragment" as="xs:string" expand-text="no"><![CDATA[<p>This is paragraph 1.<p>This is paragraph 2 line 1.<br>This is paragraph 2 line 2.]]></xsl:param>

  <xsl:output method="xhtml" indent="yes" html-version="5"/>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template name="xsl:initial-template">
    <section>
      <h2>parse-html test</h2>
      <section>
         <h3>result</h3>
         <xsl:choose>
           <xsl:when test="function-available('parse-html')" version="1.0">
             <xsl:apply-templates select="parse-html($html-fragment)"/>
           </xsl:when>
           <xsl:otherwise>
             <xsl:text>Couldn't parse HTML {$html-fragment}</xsl:text>
           </xsl:otherwise>
         </xsl:choose>
      </section>
    </section>
  </xsl:template>

  <xsl:template match="/">
    <xsl:next-match/>
    <xsl:comment>Run with <xsl:value-of select="system-property('xsl:product-name'), system-property('xsl:product-version'), system-property('Q{http://saxon.sf.net/}platform')"/></xsl:comment>
  </xsl:template>

</xsl:stylesheet>

Still don't understand why the use-when="function-available('parse-html')" doesn't work.

RE: Should support for parse-html be detectable with e.g. use-when="function-available('parse-html')"? - Added by Michael Kay over 1 year ago

Raised as issue #5826.

The following appears to work:

 <xsl:template name="xsl:initial-template">
     <xsl:variable name="ph" select="function-lookup(QName('http://www.w3.org/2005/xpath-functions', 'parse-html'), 1)"/>
     <a><xsl:value-of select="if (exists($ph)) then $ph('&lt;p>junk&lt;/p>') else 'n/a'"/></a>
  </xsl:template>

giving different results depending on --allowSyntaxExtensions

    (1-2/2)

    Please register to reply