如何在 xquery 中格式化小数?
Posted
技术标签:
【中文标题】如何在 xquery 中格式化小数?【英文标题】:How can I format a decimal in xquery? 【发布时间】:2011-08-15 20:44:34 【问题描述】:我正在尝试在 XQuery 中格式化小数。小数点是货币,所以格式应该是,###.##
。
例如:
5573652.23
应该是5,573,652.23
和
352769
应该是 352,769
(或者 352,769.00
,如果它更容易/更干净)
现在我正在使用http://www.xqueryhacker.com/2009/09/format-number-in-xquery/ 的这个函数,但我不能使用小数:
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))
)
;
我的处理器使用 Saxon 9HE。
任何帮助将不胜感激。
----- 更新 -----
根据 Dimitre 的回答,我修改了函数以保存小数部分并将其添加到返回字符串的末尾。
新功能
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 ()
)
;
【问题讨论】:
好问题,+1。请参阅我的答案以获得完整而简短的解决方案:) 标准 XPath 函数不需要使用任何命名空间前缀。如果您省略"fn:"
前缀,您的代码将更具可读性。另外,目前你的编码不一致:为什么你在concat()
函数前加上前缀,而不是substring()
函数前缀?
@Dimitre:我通常不会为标准函数添加前缀,但我从上面提到的网站复制了这个函数。这是不一致的,因为我在进行修改时没有去掉前缀。我必须通过并清理它,以免混淆任何人。再次感谢。非常感谢您的帮助!
【参考方案1】:
使用 XQuery 3.0 和 Saxon-HE 9.7 Parser,您可以执行以下操作:
declare decimal-format local:de decimal-separator = "," grouping-separator = ".";
declare decimal-format local:en decimal-separator = "." grouping-separator = ",";
let $numbers := (1234.567, 789, 1234567.765)
for $i in $numbers
return (
format-number($i,"#.###,##","local:de"),
format-number($i,"#,###.##","local:en")
)
输出是:
<?xml version="1.0" encoding="UTF-8"?>1.234,57 1,234.57 789,0 789.0 1.234.567,76
1,234,567.76
【讨论】:
【参考方案2】:这对你不起作用?:
format-number(5573652.23,",###.##")
你可以玩这个here。我很确定撒克逊人支持这个功能。
编辑:saxon 不支持此功能(请参阅下面的 cmets)。
【讨论】:
不,不支持format-number()
。那是我尝试的第一件事。我尝试从 HE 更改为 PE & EE,但仍然出现错误:F [Saxon-EE XQuery 9.3.0.4] System function format-number#2 is not available with this host language
。 +1 为一个很好的建议虽然
在 XQuery 3.0 和 Saxon-HE 9.7 Parser 中尝试了 fn:format-number($myelement/*:betrag cast as xs:decimal,"#,##0.00")
,它可以工作。【参考方案3】:
使用:
let $n := 5573652.23
return
concat(local:format-int(xs:int(floor($n))),
'.',
substring(string($n - floor($n)), 3)
)
这会产生所需的正确结果:
5,573,652.23
【讨论】:
非常感谢 Dimitre。基于这个答案,我更新了我正在使用的功能。 +1 并接受回答。以上是关于如何在 xquery 中格式化小数?的主要内容,如果未能解决你的问题,请参考以下文章