tags:

views:

66

answers:

2

I'm trying to display different information depending on incoming data. If it's an integer, I want to display just the number, if it's a decimal, I want to use 0.00# pattern. Ya, I know, a bit mixed up, but that's the development spec. :>

I have the following XSL for this specific section but I can't see to get past the xsl:when error message of

"Expected end of expression, found 'castable'. number(SAVG) -->castable <-- as xs:decimal"

<xsl:choose>
    <xsl:when test="number(SAVG) > 0">
        <xsl:choose>
            <xsl:when test="number(SAVG) castable as xs:decimal">
                <xsl:value-of select="format-number(SAVG, '###,###,##0.00#')"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="format-number(SAVG, '###,###,##0.###')"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:when>
    <xsl:when test="number(SAVG) = 0">
        <xsl:text disable-output-escaping="yes">&amp;lt;</xsl:text>1
    </xsl:when>
    <xsl:otherwise>N/A</xsl:otherwise>
</xsl:choose>

I tried looking/poking around for answers and I have tried "instance of", I've tried using xsl:if, etc but I can't seem to get this to work. Any help would be greatly appreciated.

Thanks.

From comments:

Yes, we are using 1.0. I'm sorry I'm new to the XSL processing, how do I glue your XSL and input to generate the html?

A: 

This XSLT 1.0 stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:template match="test">
        <xsl:choose>
            <!-- Not number or number less than zero -->
            <xsl:when test="0 > SVGA or number(SVGA) != SVGA">
                <xsl:text>N/A</xsl:text>
            </xsl:when>
            <!-- Number zero -->
            <xsl:when test="SVGA = 0">
                <xsl:text>&lt;1</xsl:text>
            </xsl:when>
            <!-- Integer number -->
            <xsl:when test="floor(SVGA) = SVGA">
                <xsl:value-of select="format-number(SVGA,'###,###,##0.###')"/>
            </xsl:when>
            <!-- Double number -->
            <xsl:otherwise>
                <xsl:value-of select="format-number(SVGA,'###,###,##0.00#')"/>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

With this input:

<root>
    <test>
        <SVGA>0</SVGA>
    </test>
    <test>
        <SVGA>12131</SVGA>
    </test>
    <test>
        <SVGA>123.5654</SVGA>
    </test>
    <test>
        <SVGA>-12.1</SVGA>
    </test>
    <test>
        <SVGA>-7528</SVGA>
    </test>
    <test>
        <SVGA>zero</SVGA>
    </test>
</root>

Output:

&lt;1
12,131
123.565
N/A
N/A
N/A

Edit 3: Better test order (plus Dimitre's expression), better test case, closer input sample to questioner.

Alejandro
Yes, we are using 1.0. I'm sorry I'm new to the XSL processing, how do I glue your XSL and input to generate the html?
PHenry
@PHenry: See my edit for XSLT 1.0 solution. I don't understand what you mean by `glue (...) to generate the html`. Please, post input sample and desired output.
Alejandro
re glue, oh sorry, I meant what do I need to do with those lines? I figured the XSL goes into an XSL file, and the html part goes into an html file, but I'm not sure how to reference the xsl from the html. if this is completely wacked, I apologize, I'm trying to learn as I go here.
PHenry
@PHenry: I think that you already have runned a transformation before... You should replace your `xsl:choose` instruction with the one's Dimitre or I have posted (replacing when proper, i.e. `.` with `SAVG` in mine)
Alejandro
+2  A: 

I. XSLT 1.0:

There are no xs:integer and xs:decimal in the XPath 1.0 data model used by XSLT 1.0.

Here is a code snippet that you may use:

    <xsl:choose> 
        <xsl:when test="not(floor(SAVG) = SAVG)"> 
            <xsl:value-of select="format-number(SAVG, '###,###,##0.00#')"/> 
        </xsl:when> 
        <xsl:otherwise> <!-- Integer value -->
            <xsl:value-of select="SAVG"/> 
        </xsl:otherwise> 
    </xsl:choose> 

Do note: To test if a numeric value is an integer, we use the following test:

 floor($someNum) = $someNum

Here is one way to do this:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt;
 <xsl:output method="text"/>

 <xsl:template match="/">
  <xsl:sequence select=
   "for $num in (3, 3.14)
     return
       if($num instance of xs:integer)
         then ($num, ' is xs:integer', '&#xA;')
         else if($num instance of xs:decimal)
           then ($num, ' is xs:decimal', '&#xA;')
           else ($num, ' is something else', '&#xA;')
   "/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on any XML document (not used), the wanted, correct result is produced:

3  is xs:integer 
3.14  is xs:decimal 

Or, using the format-number() function as per your example:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt;
 <xsl:output method="text"/>

 <xsl:template match="/">
  <xsl:sequence select=
   "for $num in (3, 3.14)
     return
       if($num instance of xs:integer)
         then (format-number($num, '###,###,##0.###'), '&#xA;')
         else if($num instance of xs:decimal)
           then (format-number($num, '###,###,##0.00#'), '&#xA;')
           else ()
   "/>
 </xsl:template>
</xsl:stylesheet>

produces:

3 
3.14 
Dimitre Novatchev
@Dimitre: +1 I like this XSLT 2.0 more.
Alejandro
@Dimitre: OP comments that he/she needs XSLT 1.0, now
Alejandro
@Alejandro: I added also an XSLT 1.0 solution.
Dimitre Novatchev
@Dimitre: I will +1 if I could for `fn:floor` numeric test.
Alejandro
@Alejandro: You are welcome :)
Dimitre Novatchev
OH MAN! Taking the floor of the value to test for integer/decimal? That's cool, and I thought of it too, just didn't take it to the next logical step and try it. DOH! Thank you very much guys! Awesome and it works like a charm!!!!!
PHenry