xsl-list
[Top] [All Lists]

Re: [xsl] XSLT 3.0 schema awareness vs non schema awareness

2019-02-27 02:31:49
Firstly, you need to be aware that just having a schema around doesn't itself 
cause the input to be validated. A stylesheet can have multiple inputs 
(including temporary tree variables) and the inputs are only validated if you 
ask for this. I only mention this because you didn't...

There are two main consequences of schema-awareness. One is that it enables 
stronger compile-time type-checking, which gives you better and earlier 
diagnostics when you get your code wrong. If you always get your code right 
first time, then of course you will get no benefit from this.

For example, if your stylesheet were written:

<xsl:mode typed="true"/>

<xsl:template match="test">  
       <result>
          <xsl:variable name="x" select="val"/>
          <xsl:copy-of select="$x!fn:sum(., 5)"/>
       </result>
    </xsl:template>

and if you declared fn:sum() to expect an xs:date argument, then Saxon would be 
able to tell you at compile time that the argument to fn:sum() is of the wrong 
type: it knows the type of element test (because the mode declared 
typed="true") and can therefore work out that the result of atomizing a "val" 
child will be an integer, not a date.

The second consequence of schema-awareness is that you are less dependent on 
run-time type conversions. For example, if you do distinct-values(test/val), 
then "01" and "1" are considered distinct in the untyped case, but are 
considered duplicates in the typed (schema-aware) case. There are many 
situations (like your example) where untyped values are implicitly converted to 
the required type, but there are other cases where explicit type conversion is 
needed to get the correct semantics, unless the type is already known from 
schema validation.

The article on schema-awareness that I wrote for Stylus Studio was a long time 
ago, but it is still pertinent:

http://www.stylusstudio.com/schema-aware.html

Michael Kay
Saxonica

On 27 Feb 2019, at 06:57, Mukul Gandhi 
gandhi(_dot_)mukul(_at_)gmail(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Hi all,
    Please consider following XSLT examples (I'm using the XSLT 3.0 version), 
and my questions thereafter,
(in the presented stylesheets, I'm using XPath 3.0's mapping expressions 
[using the operator !]. But my question is not about the ! operator)

I'm using Saxon EE 9.9. Saxon EE 9.7 also produces similar results.

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<test>
   <val>5</val>
   <val>4</val>
   <val>3</val>
   <val>0</val>
   <val>2</val>
   <val>0</val>
   <val>1</val>
</test>

Stylesheet 1:
(in this stylesheet, I have an embedded schema & I'm performing schema aware 
transformation)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform 
<http://www.w3.org/1999/XSL/Transform>" 
                        xmlns:xs="http://www.w3.org/2001/XMLSchema 
<http://www.w3.org/2001/XMLSchema>"
                        xmlns:fn="http://xslt-functions 
<http://xslt-functions/>"                
                        exclude-result-prefixes="xs fn"
                        version="3.0">
                
    <xsl:output method="xml" indent="yes"/>
   
    <!-- an XML schema imported into the stylesheet -->
    <xsl:import-schema>
       <xs:schema>
          <xs:element name="test">
             <xs:complexType>
                <xs:sequence>
                   <xs:element name="val" type="xs:integer" 
maxOccurs="unbounded"/>
                </xs:sequence>
             </xs:complexType>
          </xs:element>
       </xs:schema>
    </xsl:import-schema>
            
    <xsl:template match="/">  
       <result>
          <xsl:variable name="x" select="test/val"/>
          <xsl:copy-of select="$x!fn:sum(., 5)"/>
       </result>
    </xsl:template>
   
    <!-- function to add two numbers -->
    <xsl:function name="fn:sum" as="xs:integer">
       <xsl:param name="num" as="xs:integer" />
       <xsl:param name="incr" as="xs:integer" />
       
       <xsl:sequence select="$num + $incr"/>
    </xsl:function>
    
</xsl:stylesheet>

The above stylesheet, when applied to the input XML, produces following 
output,

<?xml version="1.0" encoding="UTF-8"?>
<result>10 9 8 5 7 5 6</result>

Stylesheet 2:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform 
<http://www.w3.org/1999/XSL/Transform>" 
                         xmlns:xs="http://www.w3.org/2001/XMLSchema 
<http://www.w3.org/2001/XMLSchema>"
                         xmlns:fn="http://xslt-functions 
<http://xslt-functions/>"                
                         exclude-result-prefixes="xs fn"
                         version="3.0">
                
    <xsl:output method="xml" indent="yes"/>
            
    <xsl:template match="/">  
       <result>
          <xsl:variable name="x" select="test/val" as="xs:integer*"/>
          <xsl:copy-of select="$x!fn:sum(., 5)"/>
       </result>
    </xsl:template>
   
    <!-- function to add two numbers -->
    <xsl:function name="fn:sum" as="xs:integer">
       <xsl:param name="num" as="xs:integer" />
       <xsl:param name="incr" as="xs:integer" />
       
       <xsl:sequence select="$num + $incr"/>
    </xsl:function>
    
</xsl:stylesheet>

In above stylesheet, I don't use an embedded schema and don't use schema 
aware transformation. In the above stylesheet, I add the syntax 
as="xs:integer*" to variable declaration <xsl:variable name="x" ...
The stylesheet above, produces same output as Stylesheet 1 when applied to 
the same input XML document.

Stylesheet 3:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform 
<http://www.w3.org/1999/XSL/Transform>" 
                         xmlns:xs="http://www.w3.org/2001/XMLSchema 
<http://www.w3.org/2001/XMLSchema>"
                         xmlns:fn="http://xslt-functions 
<http://xslt-functions/>"                
                         exclude-result-prefixes="xs fn"
                         version="3.0">
                
    <xsl:output method="xml" indent="yes"/>
            
    <xsl:template match="/">  
       <result>
          <xsl:variable name="x" select="test/val" />
          <xsl:copy-of select="$x!fn:sum(., 5)"/>
       </result>
    </xsl:template>
   
    <!-- function to add two numbers -->
    <xsl:function name="fn:sum" as="xs:integer">
       <xsl:param name="num" as="xs:integer" />
       <xsl:param name="incr" as="xs:integer" />
       
       <xsl:sequence select="$num + $incr"/>
    </xsl:function>
    
</xsl:stylesheet>

In the above stylesheet, I don't use as="xs:integer*" on the mentioned 
variable. Otherwise, the above stylesheet is same as Stylesheet 2.
The stylesheet above, produces same output as stylesheets 1 and 2 when 
applied to the same input XML document.

That is, all above three stylesheets produce same output with the same input 
XML document.

I wish to know the, pros and cons when comparing above three mentioned 
stylesheets, in terms of functionality, performance and may be other factors. 
I guess, schema aware transformations in general, are more suited when 
rigorous static type checking is needed.
 



-- 
Regards,
Mukul Gandhi

alt address : mukulgandhi(_at_)acm(_dot_)org 
<mailto:mukulgandhi(_at_)acm(_dot_)org>
XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/293509> (by 
email <>)
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>