Project

Profile

Help

Different treatment of error in group-starting-with pattern

Added by Martin Honnen over 3 years ago

Making a coding error I found that Saxon Java (tested with HE 10.5) and Saxon-JS 2.2 (tested under Node.js as well as in the browser) treat an error in the group-starting-with pattern differently, the Java version ignores it while the JS versions throws an error.

The spec https://www.w3.org/TR/xslt-30/#pattern-errors says:

A dynamic error or type error that occurs during the evaluation of a pattern against a particular item has the effect that the item being tested is treated as not matching the pattern. The error does not cause the transformation to fail

so based on that it seems Saxon-JS should not fail to transform a document.

Reduced test case (coding error is in group-starting-with=".[$starting-with-condition]" instead of group-starting-with=".[$starting-with-condition(.)]"):

<?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:mf="http://example.com/mf"
  exclude-result-prefixes="#all"
  expand-text="yes">
  
  <xsl:function name="mf:group-starting-with" as="item()*">
    <xsl:param name="population" as="item()*"/>
    <xsl:param name="starting-with-condition" as="function(item()) as xs:boolean"/>
    <xsl:param name="handle-group" as="function(item()*) as item()*"/>
    <xsl:for-each-group select="$population" group-starting-with=".[$starting-with-condition]">
      <xsl:choose>
        <xsl:when test="$starting-with-condition(.)">
          <xsl:sequence select="$handle-group(current-group())"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="current-group()"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each-group>
  </xsl:function>
  
  <xsl:function name="mf:wrap-group" as="element()">
    <xsl:param name="group" as="item()*"/>
    <xsl:param name="wrapper-name" as="xs:QName"/>
    <xsl:element name="{$wrapper-name}" namespace="{namespace-uri-from-QName($wrapper-name)}">
      <xsl:apply-templates select="$group"/>
    </xsl:element>
  </xsl:function>
  
  <xsl:template match="body">
    <xsl:copy>
      <xsl:sequence
        select="mf:group-starting-with(
                  *,
                  function($el) { $el instance of element(h1) },
                  mf:wrap-group#2(?, QName('', 'section'))
                )"/>
    </xsl:copy>
  </xsl:template>

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

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="/" name="xsl:initial-template">
    <xsl:next-match/>
    <xsl:comment xmlns:saxon="http://saxon.sf.net/">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>

When run against a sample like

<?xml version="1.0" encoding="UTF-8"?>
<html>
    <head>
        <title>Example</title>
    </head>
    <body>
        <h1>Heading 1, 1</h1>
        <p>Paragraph 1, 1</p>
        <p>Paragraph 1, 2</p>
        <h1>Heading 2, 1</h1>
        <p>Paragraph 2, 1</p>
        <p>Paragraph 2, 2</p>
        <h1>Heading 3, 1</h1>
        <p>Paragraph 3, 1</p>
        <p>Paragraph 3, 2</p>
    </body>
</html>

Saxon-JS 2.2 under Node.js 14 outputs

<!DOCTYPE html>
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Example</title>
   </head>Transformation failure: Error FORG0006 at group-starting-with-test1-predicate-error.xsl#13
    Effective boolean value is not defined for functions
Error FORG0006 at group-starting-with-test1-predicate-error.xsl#13
    Effective boolean value is not defined for functions

That output suggests the transformation is started but the dynamic error in the pattern causes the transformation to fail while it should rather only make the processor treat the element as not being matched, if I understand the spec correctly.

Saxon Java treats the error in the pattern by not matching it seems and outputs

<!DOCTYPE HTML><html>

   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

      <title>Example</title>
      </head>

   <body>
      <section>
         <h1>Heading 1, 1</h1>
         <p>Paragraph 1, 1</p>
         <p>Paragraph 1, 2</p>
         <h1>Heading 2, 1</h1>
         <p>Paragraph 2, 1</p>
         <p>Paragraph 2, 2</p>
         <h1>Heading 3, 1</h1>
         <p>Paragraph 3, 1</p>
         <p>Paragraph 3, 2</p>
      </section>
   </body>
   </html><!--Run with SAXON HE 10.5 -->

Please register to reply