2010-01-07 128 views
2

我有一個XML文檔,其中應報告特定xs:decimal的小數位數保存在兄弟節點中。我目前正在努力尋找一種簡單的方法來通過format-number函數輸出。XPath格式 - 基於變量的具有小數位數的數字?

我可以用一些其他函數構建一個圖片字符串,但是對於應該是什麼(至少是imo)而言,這看起來非常囉嗦,這是一個相對直接和常見的任務。

例如我目前正在做的是這樣的:

<xsl:value-of 
select="format-number(myNode/DecimalValue, 
     concat('#0.', 
       string-join(for $i in 1 to myNode/DecimalPlaces return '0'))" 
/> 

有沒有更好的方法?

+1

對不起,爲什麼不簡單地使用'round($ value * 100)div 100'? – iosadchii 2012-06-23 16:00:14

+0

因爲這不會添加尾隨零。例如如果myNode/DecimalPlaces = 4,我希望數字100輸出爲100.0000 – adhocgeek 2012-09-13 17:02:16

回答

4

非常好的問題!這通常意味着,我不知道答案,但我希望別人也這樣做,因爲這對我也是一種痛苦。

無論如何,我做了一些搜索,我認爲round-half-to-even功能可能做的伎倆(http://www.xqueryfunctions.com/xq/fn_round-half-to-even.html

您的代碼將變爲:

<xsl:value-of 
    select=" 
    round-half-to-even(
     myNode/DecimalValue 
    , myNode/DecimalPlaces 
    ) 
    " 
/> 

現在過了一小角正切: 對於人們使用XSLT 1.1或更低和XPath 1,你可以這樣做:

<xsl:value-of 
    select=" 
    concat(
     substring-before(DecimalValue, '.') 
    , '.' 
    , substring(substring-after(DecimalValue, '.'), 1, DecimalPlaces -1) 
    , round(
     concat(
      substring(substring-after(DecimalValue, '.'), DecimalPlaces, 1) 
     , '.' 
     , substring(substring-after(DecimalValue, '.'), DecimalPlaces+1) 
     ) 
    ) 
    ) 
    " 
/> 

當然,這種合作de是比原來的更差,但如果有人知道如何解決XPath 1的原始問題,並且比這更好的想法,我很樂意聽到這個。 (越來越多的時候,我希望世界會完全跳過XML並立即採取行動,JSON)

+0

是的。我是一個沉重的客戶端瀏覽器XSLT用戶。嘲笑我,但它對我需要做的事很好。但由於某種原因(我有一種預感,爲什麼)所有的瀏覽器仍然停留在XSLT 1.1/XPath 1.因此,在某些時候,你只需要吸取它,並折磨一些小貓以完成工作。像這樣的事情出現了。謝天謝地,有很多好東西來彌補這種廢話。 – 2010-01-07 19:05:35

2
<!-- use a generous amount of zeros in a top-level variable --> 
<xsl:variable name="zeros" select="'000000000000000000000000000000000'" /> 

<!-- …time passes… --> 
<xsl:value-of select=" 
    format-number(
    myNode/DecimalValue, 
    concat('#0.', substring($zeros, 1, myNode/DecimalPlaces)) 
) 
" /> 

你可以將它抽象掉成模板:

<!-- template mode is merely to prevent collisions with other templates --> 
<xsl:template match="myNode" mode="FormatValue"> 
    <xsl:value-of select=" 
    format-number(
     DecimalValue, 
     concat('#0.', substring($zeros, 1, DecimalPlaces)) 
    ) 
    " /> 
</xsl:template> 

<!-- call like this --> 
<xsl:apply-templates select="myNode" mode="FormatValue" /> 

你也可以做一個命名模板,並在調用它時使用XSLT上下文節點。取決於您的輸入文檔,如果這對您是可行的,則需要。

<xsl:template name="FormatValue"> 
    <!-- same as above --> 
</xsl:template> 

<!-- call like this --> 
<xsl:for-each select="myNode"> 
    <xsl:call-template name="FormatValue" /> 
</xsl:for-each> 
+0

+1看起來很完美 – Filburt 2010-01-07 17:25:37

+0

是的,那是另一種方式。我知道我不能通過說我也這樣想,但我做到了,我沒有發佈它,因爲OP要求有一個更好的方法來做到這一點。我沒有考慮到這一點,因爲我沒有看到預先知道最大精確度的跡象。 就個人而言,如果我出於某種原因不能使用'round-half-to-even()',並且知道最大精度,我肯定會使用這樣的解決方案。 這就是說,我非常同意OP,它只是香蕉這個簡單的東西在XPath/XSLT中非常困難 – 2010-01-07 19:02:30

+0

一個小優化可能是擺脫** concat()**並把'#0 「。進入常量然後子字符串** DecimalPlaces + 3。** – Filburt 2010-01-08 08:19:25

相關問題