This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 29237 - [xslt 3.0] Bug in CSV package example
Summary: [xslt 3.0] Bug in CSV package example
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Last Call drafts
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-10-24 13:44 UTC by Michael Kay
Modified: 2015-11-05 18:43 UTC (History)
1 user (show)

See Also:


Attachments

Description Michael Kay 2015-10-24 13:44:01 UTC
In the example CSV package in 3.5.7.8, we have a variable declaration

<xsl:variable name="csv:csv-quote-ok" visibility="private">
   <xsl:sequence select="
       if (string-length($csv:quote) ne 1) 
       then error(xs:QName('csv:ERR001'), 
                  'Incorrect length for $csv:quote, should be 1') 
       else ()" />
</xsl:variable>

and we say: 

When the value of csv:quote is suitable, the variable csv:csv-quote-ok will evaluate to the empty sequence

But this is incorrect. Because the variable declaration has no "as" attribute, the value is not an empty sequence but a childless document node.

I am fixing this by changing the variable declaration to:

<xsl:variable name="csv:csv-quote-ok" visibility="private" 
              as="xs:error?" select="
       if (string-length($csv:quote) ne 1) 
       then error(xs:QName('csv:ERR001'), 
                  'Incorrect length for $csv:quote, should be 1') 
       else ()" />
Comment 1 Michael Kay 2015-10-24 13:59:21 UTC
To be honest, I'm still slightly uneasy about this mechanism. XPath "errors and optimisation" says that if an expression has only one possible value, other than an error, the system doesn't need to evaluate it merely in order to test for the error. So an optimizing processor doesn't need to evaluate csv-quote-ok.

And in any case, the mechanism is clearly a hack.

A clean solution would be to declare a type:

<xsl:import-schema>
  <xs:schema targetNamespace="http://example.com/csv">
    <xs:simpleType name="one-char">
      <xs:restriction base="xs:string">
        <xs:length value="1"/>
      </
    </
  </
</

and then declare the variable to have this type:

<xsl:variable name="csv:quote" as="csv:one-char" select="csv:one-char('&quot;')" visibility="public"/>

Any overriding variable is required to have the same type.

Although I know there are practical problems because schema-awareness is not offered by all processors, this seems a much worthier solution to include in a spec where we are supposed to be demonstrating good practice. The way to constrain the type of a variable is by using the "as" attribute.
Comment 2 Michael Kay 2015-10-24 14:21:15 UTC
Unfortunately the solution proposed in comment #1 opens up further questions. If a using stylesheet wishes to override the variable csv:quote, then it needs to declare its type as csv:one-char. But this type name is not in scope unless the using package imports the schema for the csv namespace: and how do you import a schema that is defined inline in another package?

To solve this, I suggest adding the following rule to xsl:import-schema:

When package P uses package Q, the schema components imported by package Q do not automatically become available in package P. However, if package P contains an xsl:import-schema declaration with namespace=N, then any schema components in namespace N that are imported by package Q also become available in package P. There is no need in this case to specify a schema-location attribute, and any such attribute is ignored. This includes the case where the xsl:import-schema declaration in package Q defines an inline schema, that is, where it has an xs:schema element as a child.
Comment 3 Michael Kay 2015-11-01 15:33:30 UTC
I have adopted the solution of using a second (private) variable $csv:validated-quote which is set to the value of $csv:quote provided it is valid. This seems easier to explain and involves less hackery. It is still subject to the objection that when an expression is either a known value or an error, the error checking can be bypassed, but it's probably pretty safe in practice.

Since this is an example and therefore editorial, I am marking it as resolved.