2011-04-30 70 views
5

Estoy tratando de formatear decimales en XQuery. Los decimales son moneda, por lo que el formato debe ser ,###.##.¿Cómo puedo formatear un decimal en xquery?

Por ejemplo:

5573652.23 debería ser 5,573,652.23

y

352769 debe ser 352,769 (o 352,769.00 si es más fácil/limpiador)

En este momento estoy usando esta función desde http://www.xqueryhacker.com/2009/09/format-number-in-xquery/, pero no puedo usar decimales con él:

declare function local:format-int($i as xs:int) as xs:string 
{ 
    let $input := 
    if ($i lt 0) then fn:substring(fn:string($i), 2) 
    else fn:string($i) 
    let $rev := fn:reverse(fn:string-to-codepoints(fn:string($input))) 
    let $comma := fn:string-to-codepoints(',') 

    let $chars := 
    for $c at $i in $rev 
    return (
     $c, 
     if ($i mod 3 eq 0 and fn:not($i eq count($rev))) 
     then $comma else() 
    ) 

    return fn:concat(
    if ($i lt 0) then '-' else(), 
    fn:codepoints-to-string(fn:reverse($chars)) 
) 
}; 

Estoy usando Saxon 9HE para mi procesador.

Cualquier ayuda sería muy apreciada.

ACTUALIZACIÓN ----- -----

Sobre la base de la respuesta de Dimitre, que modifica la función para guardar la parte decimal y añadirlo al final de la cadena de retorno.

nueva función

declare function local:format-dec($i as xs:decimal) as xs:string 
{ 
    let $input := tokenize(string(abs($i)),'\.')[1] 
    let $dec := substring(tokenize(string($i),'\.')[2],1,2) 
    let $rev := reverse(string-to-codepoints(string($input))) 
    let $comma := string-to-codepoints(',') 

    let $chars := 
    for $c at $i in $rev 
    return (
     $c, 
     if ($i mod 3 eq 0 and not($i eq count($rev))) 
     then $comma else() 
    ) 

    return concat(if ($i lt 0) then '-' else(), 
       codepoints-to-string(reverse($chars)), 
       if ($dec != '') then concat('.',$dec) else() 
       ) 
}; 
+0

Buena pregunta, 1. Vea mi respuesta para una solución completa y breve :) –

+0

No es necesario usar ningún prefijo de espacio de nombres para las funciones estándar de XPath. Si omite el prefijo '" fn: "', su código será más legible. Además, actualmente su codificación es inconsistente: ¿por qué usted prefija la función 'concat()', pero no la función 'substring()'? –

+0

@Dimitre: normalmente no prefijo las funciones estándar, pero copié esta función del sitio web mencionado anteriormente. Es inconsistente porque no quité los prefijos cuando hice las modificaciones. Tendré que revisarlo y limpiarlo para que no confunda a nadie. Gracias de nuevo. ¡Su ayuda es muy apreciada! –

Respuesta

3

Uso:

let $n := 5573652.23 
return 
     concat(local:format-int(xs:int(floor($n))), 
      '.', 
      substring(string($n - floor($n)), 3) 
      ) 

Esto produce exactamente el resultado deseado, correcta:

5,573,652.23 
+0

Muchas gracias Dimitre. En base a esta respuesta, actualicé la función que estaba usando. +1 y respuesta aceptada. –

+0

@DevNull: De nada. –

0

Esto no funciona para usted ?:

format-number(5573652.23,",###.##") 

se puede jugar con este here. Estoy bastante seguro de que saxon admite esta función.

Editar: Esta función no es compatible con saxon (consulte los comentarios a continuación).

+1

No, 'format-number()' no es compatible. Eso fue lo primero que intenté. Intenté cambiar de HE a PE y EE, pero sigo teniendo un error: 'F [Saxon-EE XQuery 9.3.0.4] El formato de la función del sistema número 2 no está disponible con este lenguaje de host'. +1 para una buena sugerencia, aunque –

+0

'format-number()' está en el alcance para XSLT solamente. –

Cuestiones relacionadas