Subject: Re: [xsl] [XSLT 2.0] Determining the datatype of the value returned from a function? From: Dimitre Novatchev <dnovatchev@xxxxxxxxx> Date: Sat, 18 Jun 2005 07:38:57 +1000 |
This reminds me that there is such a function in FXSL -- int:type(). I regard this as a very light implementation -- more (as type objects) is to come in the future. Cheers, Dimitre Novatchev. P.S. The code <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xdt="http://www.w3.org/2005/04/xpath-datatypes" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="http://fxsl.sf.net/" xmlns:int="http://fxsl.sf.net/internal/type" exclude-result-prefixes="f xs xdt int" > <xsl:output omit-xml-declaration="yes"/> <xsl:template match="/"> xs:token('abc') : <xsl:value-of select="int:type(xs:token('abc'))"/> -1 : <xsl:value-of select="int:type(-1)"/> xs:negativeInteger(-1) : <xsl:value-of select="int:type(xs:negativeInteger(-1))"/> xs:nonPositiveInteger(0) : <xsl:value-of select="int:type(xs:nonPositiveInteger(0))"/> 0 : <xsl:value-of select="int:type(0)"/> 3 : <xsl:value-of select="int:type(3)"/> 3. : <xsl:value-of select="int:type(3.)"/> 3.0E1 : <xsl:value-of select="int:type(3.0E1)"/> xs:float(3) : <xsl:value-of select="int:type(xs:float(3))"/> xs:positiveInteger(3) : <xsl:value-of select="int:type(xs:positiveInteger(3))"/> '3' : <xsl:value-of select="int:type('3')"/> /*/*/text() : <xsl:value-of select="int:type(/*/*/text())"/> data(/*/*/text()[1]) : <xsl:value-of select="int:type(data(/*/*/text()[1]))"/> </xsl:template> <xsl:function name="int:type" as="xs:string"> <xsl:param name="pThis"/> <xsl:choose> <xsl:when test="$pThis instance of xs:decimal"> <xsl:choose> <xsl:when test="$pThis instance of xs:unsignedByte">xs:unsignedByte</xsl:when> <xsl:when test="$pThis instance of xs:unsignedShort">xs:unsignedShort</xsl:when> <xsl:when test="$pThis instance of xs:unsignedInt">xs:unsignedInt</xsl:when> <xsl:when test="$pThis instance of xs:unsignedLong">xs:unsignedLong</xsl:when> <xsl:when test="$pThis instance of xs:positiveInteger">xs:positiveInteger</xsl:when> <xsl:when test="$pThis instance of xs:nonNegativeInteger">xs:nonNegativeInteger</xsl:when> <xsl:when test="$pThis instance of xs:negativeInteger">xs:negativeInteger</xsl:when> <xsl:when test="$pThis instance of xs:nonPositiveInteger">xs:nonPositiveInteger</xsl:when> <xsl:when test="$pThis instance of xs:byte">xs:byte</xsl:when> <xsl:when test="$pThis instance of xs:short">xs:short</xsl:when> <xsl:when test="$pThis instance of xs:int">xs:int</xsl:when> <xsl:when test="$pThis instance of xs:long">xs:long</xsl:when> <xsl:when test="$pThis instance of xs:integer">xs:integer</xsl:when> <xsl:otherwise>xs:decimal</xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$pThis instance of xs:double">xs:double</xsl:when> <xsl:when test="$pThis instance of xs:float">xs:float</xsl:when> <xsl:when test="$pThis instance of xs:string"> <xsl:choose> <xsl:when test="$pThis instance of xs:NMTOKEN">xs:NMTOKEN</xsl:when> <!-- <xsl:when test="$pThis instance of xs:NMTOKENS">xs:NMTOKENS</xsl:when> --> <!-- <xsl:when test="$pThis instance of xs:ENTITIES">xs:ENTITIES</xsl:when> --> <xsl:when test="$pThis instance of xs:ENTITY">xs:ENTITY</xsl:when> <!-- <xsl:when test="$pThis instance of xs:IDREFS">xs:IDREFS</xsl:when> --> <xsl:when test="$pThis instance of xs:IDREF">xs:IDREF</xsl:when> <xsl:when test="$pThis instance of xs:ID">xs:ID</xsl:when> <xsl:when test="$pThis instance of xs:NCName">xs:NCName</xsl:when> <xsl:when test="$pThis instance of xs:Name">xs:Name</xsl:when> <xsl:when test="$pThis instance of xs:language">xs:language</xsl:when> <xsl:when test="$pThis instance of xs:token">xs:token</xsl:when> <xsl:when test="$pThis instance of xs:normalizedString">xs:normalizedString</xsl:when> <xsl:otherwise>xs:string</xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$pThis instance of xs:boolean">xs:boolean</xsl:when> <xsl:when test="$pThis instance of xs:duration">xs:duration</xsl:when> <xsl:when test="$pThis instance of xs:dateTime">xs:dateTime</xsl:when> <xsl:when test="$pThis instance of xs:time">xs:time</xsl:when> <xsl:when test="$pThis instance of xs:date">xs:date</xsl:when> <xsl:when test="$pThis instance of xs:gYearMonth">xs:gYearMonth</xsl:when> <xsl:when test="$pThis instance of xs:gYear">xs:gYear</xsl:when> <xsl:when test="$pThis instance of xs:gMonthDay">xs:gMonthDay</xsl:when> <xsl:when test="$pThis instance of xs:gDay">xs:gDay</xsl:when> <xsl:when test="$pThis instance of xs:gMonth">xs:gMonth</xsl:when> <xsl:when test="$pThis instance of xs:base64Binary">xs:base64Binary</xsl:when> <xsl:when test="$pThis instance of xs:hexBinary">xs:hexBinary</xsl:when> <xsl:when test="$pThis instance of xs:anyURI">xs:anyURI</xsl:when> <xsl:when test="$pThis instance of xs:QName">xs:QName</xsl:when> <xsl:when test="$pThis instance of xs:NOTATION">xs:NOTATION</xsl:when> <xsl:when test="$pThis instance of xdt:untypedAtomic">xdt:untypedAtomic</xsl:when> <xsl:otherwise>Unknown xdt:untypedAtomic</xsl:otherwise> </xsl:choose> </xsl:function> </xsl:stylesheet> On 6/18/05, Roger L. Costello <costello@xxxxxxxxx> wrote: > Many thanks David. A subtle, but extremely important point. > > I figure that others may encounter this problem, so below I have summarized > the problem and its solution. /Roger > > Determining the datatype of the value returned by a function > > Suppose that you want to create an XSLT function which returns a value that > may be one of any number of different (atomic) datatypes, e.g., xs:integer, > xs:double, xs:decimal, xs:string, etc. > > With the value that the function returns you would like to determine its > datatype. For example, if the function returns the integer 5 then: > > "$value instance of xs:integer" > > should yield true (assume that $value is a variable that holds the value > returned from the function). > > Here is an example that shows invoking a function and then testing the value > that is > returned to determine its datatype: > > <xsl:template match="/"> > <xsl:variable name="test1" select="'A'"/> > <xsl:variable name="value" select="ex:Test($test1)"/> > <xsl:choose> > <xsl:when test="$value instance of xsd:integer"> > <xsl:message>INTEGER</xsl:message> > </xsl:when> > <xsl:when test="$value instance of xsd:string"> > <xsl:message>STRING</xsl:message> > </xsl:when> > ... > <xsl:otherwise> > <xsl:message>OTHER</xsl:message> > </xsl:otherwise> > </xsl:choose> > </xsl:template> > > How you design the function is crucial. The below function gives > undesirable results. > It always returns a text node that contains a string value: > > <xsl:function name="ex:Test"> > <xsl:param name="letter"/> > <xsl:choose> > <xsl:when test="$letter eq 'A'"> > <xsl:variable name="num" select="5" as="xsd:integer"/> > <xsl:value-of select="$num"/> > </xsl:when> > <xsl:when test="$letter eq 'B'"> > <xsl:variable name="num" select="5.00" as="xsd:decimal"/> > <xsl:value-of select="$num"/> > </xsl:when> > ... > <xsl:otherwise> > <xsl:variable name="message" select="'Error'" as="xsd:string"/> > <xsl:value-of select="$message"/> > </xsl:otherwise> > </xsl:choose> > </xsl:function> > > Consider this code snippet: > > <xsl:variable name="num" select="5" as="xsd:integer"/> > <xsl:value-of select="$num"/> > > You might think that the xsl:value-of element will output an integer 5. > In fact, it will not. The xsl:value-of statement always outputs: > 1. A text node, and > 2. The datatype of the value in the text node is always string. > That is, with the xsl:value-of element you will always loose > datatype information. Beware! > > Now consider this code snippet: > > <xsl:variable name="num" select="5" as="xsd:integer"/> > <xsl:sequence select="$num"/> > > The xsl:sequence element behaves very differently from the xsl:value-of > element. In the above example, the xsl:sequence element will simply > output the number 5, with the integer datatype intact. > So, if we want to create a function that returns an atomic value, and we > want > the datatype of the atomic value intact, then the function must use > xsl:sequence, > and it must not use xsl:value-of. > > Here is the correct way to design the function: > > <xsl:function name="ex:Test"> > <xsl:param name="letter"/> > <xsl:choose> > <xsl:when test="$letter eq 'A'"> > <xsl:variable name="num" select="5" as="xsd:integer"/> > <xsl:sequence select="$num"/> > </xsl:when> > <xsl:when test="$letter eq 'B'"> > <xsl:variable name="num" select="5.00" as="xsd:decimal"/> > <xsl:sequence select="$num"/> > </xsl:when> > ... > <xsl:otherwise> > <xsl:variable name="message" select="'Error'" as="xsd:string"/> > <xsl:sequence select="$message"/> > </xsl:otherwise> > </xsl:choose> > </xsl:function> > > Here's a complete example, that works as desired: > > <xsl:function name="ex:Test"> > <xsl:param name="letter"/> > <xsl:choose> > <xsl:when test="$letter eq 'A'"> > <xsl:variable name="num" select="5" as="xsd:integer"/> > <xsl:sequence select="$num"/> > </xsl:when> > <xsl:otherwise> > <xsl:variable name="message" select="'Error'" as="xsd:string"/> > <xsl:sequence select="$message"/> > </xsl:otherwise> > </xsl:choose> > </xsl:function> > > <xsl:template match="/"> > <xsl:variable name="test1" select="'A'"/> > <xsl:variable name="result" select="ex:Test($test1)"/> > <xsl:choose> > <xsl:when test="$result instance of xsd:integer"> > <xsl:message>INTEGER</xsl:message> > </xsl:when> > <xsl:when test="$result instance of xsd:string"> > <xsl:message>STRING</xsl:message> > </xsl:when> > <xsl:when test="$result instance of xdt:anyAtomicType"> > <xsl:message>xdt:anyAtomicType</xsl:message> > </xsl:when> > <xsl:when test="$result instance of text()"> > <xsl:message>text()</xsl:message> > </xsl:when> > <xsl:otherwise> > <xsl:message>OTHER</xsl:message> > </xsl:otherwise> > </xsl:choose> > </xsl:template>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] [XSLT 2.0] Determining th, David Carlisle | Thread | [xsl] Filtering XML elements based , Ramon Felciano |
RE: [xsl] Ingoring HTML, Jay Burgess | Date | Re: [xsl] preceding/following chara, Bruce D'Arcus |
Month |