[xsl] testing for string and number in XSLT 2.0 was Re: [xsl] Test For Numeric Values?

Subject: [xsl] testing for string and number in XSLT 2.0 was Re: [xsl] Test For Numeric Values?
From: James Fuller <jim.fuller@xxxxxxxxxxxxxx>
Date: Fri, 08 Apr 2005 13:01:16 +0200
after a little bit of thinking, decided regexps might be a better way to
go to match a number and/or string when one cannot resort to anything
schema based.....

the following example xml/xslt has a few limitations ( like data has to
be in discrete tokens..) have created a few functions with xsl:function
which does a loose type checking for string or numbers.

example xml

<?xml version="1.0" encoding="UTF-8"?>
<example>
    <test>123123</test>
    <test>lkhjklhj</test>
</example>


example xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="2.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema";
    xmlns:type="http://www.ruminate.co.uk/type";>
    <xsl:output method="xml" indent="yes"/>
   
    <xsl:variable name="x" select="example/test[1]" as="xs:integer"/>
    <xsl:template match="example">

        Test matching number
        using istype:<xsl:value-of select="type:istype(test[1],'number')"/>
        using isnumber:<xsl:value-of select="type:isnumber(test[1])"/>
        using isstring:<xsl:value-of select="type:isstring(test[1])"/>

        Test matching string
        using istype:<xsl:value-of select="type:istype(test[2],'string')"/>
        using isnumber:<xsl:value-of select="type:isnumber(test[2])"/>
        using isstring:<xsl:value-of select="type:isstring(test[2])"/>

    </xsl:template>             
  
    <xsl:function name="type:isnumber">
        <xsl:param name="select"/>
        <xsl:choose>
            <xsl:when test="$select">
               
                <xsl:analyze-string select="$select" regex="[\d]+"
flags="m">
                    <xsl:matching-substring>
                        <xsl:value-of select="true()"/>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="false()"/>                   
                    </xsl:non-matching-substring>
                </xsl:analyze-string>                  
               
            </xsl:when>   
            <xsl:otherwise>
                NaN
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>
   
    <xsl:function name="type:isstring">
        <xsl:param name="select"/>
        <xsl:choose>
            <xsl:when test="$select">
               
                <xsl:analyze-string select="$select"
regex="[A-Z,a-z,\s]+" flags="m">
                    <xsl:matching-substring>
                        <xsl:value-of select="true()"/>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="false()"/>                   
                    </xsl:non-matching-substring>
                </xsl:analyze-string>                  
               
            </xsl:when>   
            <xsl:otherwise>
                NaN
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>   
           
    <xsl:function name="type:istype">
        <xsl:param name="select"/>
        <xsl:param name="type"/>
        <xsl:choose>
            <xsl:when test="$type='string' or $type='s'">

                <xsl:analyze-string select="$select"
regex="[A-Z,a-z,\s]+" flags="m">
                    <xsl:matching-substring>
                    <xsl:value-of select="true()"/>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="false()"/>                   
                    </xsl:non-matching-substring>
                </xsl:analyze-string>  
               
               
            </xsl:when>
            <xsl:when test="$type='number' or $type='n'">
               
                <xsl:analyze-string select="$select" regex="[\d]+"
flags="m">
                    <xsl:matching-substring>
                        <xsl:value-of select="true()"/>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="false()"/>
                    </xsl:non-matching-substring>
                </xsl:analyze-string>
               
               
            </xsl:when>
            <xsl:otherwise>
                NaN
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>
</xsl:stylesheet>


this is fine and dandy in a basic XSLT 2.0 processor, and potentiall
could be extended, though I find it uncomfortable that xsl:function
automatically casts my params as xs:string when there is no declaration,
so doing something like the following (in an XSLT 2.0 processor that is
schema aware).


        Test X (xs:integer) matching string
        using istype:<xsl:value-of select="type:istype($x,'number')"/>
        using isnumber:<xsl:value-of select="type:isnumber($x)"/>
        using isstring:<xsl:value-of select="type:isstring($x)"/>

will through out an error, I guess I could employ the use-when attribute
to check for schema conformance (does this exist as a system property?).

btw, does anyone else find it weird that xsl:function doesnt have the
ability to prescribe a return type ?...I wanted to return a boolean
type...but found doing something like <xsl:value-of select="true()"/> to
be awkward.
 
cheers, Jim Fuller

Current Thread