使用 XSLT 2.0 或 3.0 对字符串执行算术运算时出现问题

Issues while performing Arithmetic Operations on Strings using XSLT 2.0 or 3.0

我在对以下 XML

进行算术运算时遇到问题

来源XML

<?xml version="1.0" encoding="UTF-8"?>
<Compensation>
    <Salary>
        <BasePay>600.12</BasePay>
        <Bonus>00.99</Bonus>
        <Gym>0</Gym>
        <Tax>,000</Tax>
    </Salary>
    <Salary>
        <BasePay>600.12</BasePay>
        <Bonus>00.99</Bonus>
        <Gym/>
        <Tax>,000</Tax>
    </Salary> 
</Compensation>

当前 XSLT

<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:this="urn:this-stylesheet"
        
        exclude-result-prefixes="xs this"
        version="2.0">
        <xsl:output method="xml" indent="yes"/>
        
       
        
        <xsl:function name = "this:translateCurrency">
            <xsl:param name="stringValue"/>        
            <xsl:value-of select="format-number(xs:decimal(translate(xs:string($stringValue), '$,','')), '#.##')"/>       
        </xsl:function>    
        
        
        <xsl:template match="Compensation">
            <Worker>
            <xsl:for-each select="Salary">
                <Comp>
                <Amount>                
                    <xsl:value-of select="this:translateCurrency(BasePay) - this:translateCurrency(Tax)  "/>
                </Amount>
                
                <NoBonus>
                    <xsl:value-of select="this:translateCurrency(BasePay) + this:translateCurrency(Gym)  "/>
                </NoBonus>
                </Comp>
            </xsl:for-each>       
            </Worker>
            
        </xsl:template>
    </xsl:stylesheet>

货币符号和逗号将始终出现在与金额相关的 XML 元素中,例如我正在翻译和转换的 <BasePay> <Bonus> <Gym> <Tax>在加减之前转换为小数。

有两个问题

1. 因为我的来源 XML 有很多与 Amount 相关的字段,所以我已经声明了一个用于转换和转换为十进制的函数。但是,我无法将函数四舍五入到小数点后两位。我期待我的函数中的以下代码行能够四舍五入到小数点后两位。

<xsl:value-of select="format-number(xs:decimal(translate(xs:string($stringValue), '$,','')), '#.##')"/>

2. 某些金额字段可能为空,例如<Gym/> 在我的来源 XML 和当前版本的 XSLT returns 中为空 无法将字符串“”转换为 xs:decimal 值中没有数字.

我在 xsl:function 语句和 Gym!='' 中尝试了 $stringValue!='',但无济于事。

谁能帮我弄清楚我应该怎么做才能使我的函数四舍五入到小数点后两位并克服 no digits in value 错误?

<NoBonus>
  <xsl:value-of select="this:translateCurrency(BasePay) + this:translateCurrency(Gym!='')  "/>
</NoBonus>

预期结果

<?xml version="1.0" encoding="UTF-8"?>
<Worker>
   <Comp>
      <Amount>-11399.88</Amount>
      <NoBonus>19270.12</NoBonus>
   </Comp>
   <Comp>
      <Amount>-21399.88</Amount>
      <NoBonus>28600.12</NoBonus>
   </Comp>
</Worker>

如果要将字符串转换为十进制值,请不要在其上使用 format-number。因此,要将您的输入值转换为 xs:decimals,您需要例如

<xsl:function name="this:translateCurrency" as="xs:decimal">
  <xsl:param name="input" as="xs:string"/>
  <xsl:sequence
    select="if ($input = '') 
            then 0
            else xs:decimal(translate($input, '$,', ''))"/>
</xsl:function>

然后在任何算术计算中使用这些 xs:decimal 值,仅当您需要以某种格式输出算术计算的最终结果时,才对该结果使用 format-number 以确保例如你得到两位小数。