Subject: RE: [xsl] [XSLT 2.0] Determining the datatype of the value returned from a function? From: "Roger L. Costello" <costello@xxxxxxxxx> Date: Fri, 17 Jun 2005 13:59:45 -0400 |
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 | Re: [xsl] [XSLT 2.0] Determining th, David Carlisle |
[xsl] Removing entity in specific e, Joe Stump | Date | Re: [xsl] Filtering XML elements ba, Sam D. Chuparkoff |
Month |