替换xml中的unnessary字符并将它们相加

时间:2013-12-05 07:23:55

标签: xml xslt xslt-grouping

我是XSLT的新手,我需要添加所有价格值。但是XML中的价格值有' - '而且没有值,而在做总结时我得到的是NaN。所以我尝试了下面的XSL,但我仍然无法实现我的结果。

以下是XML示例

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Edited by XMLSpy® -->
<root>
  <qwe>
    <value>+1</value>
  </qwe>
  <qwe>
    <value>20</value>
  </qwe>
  <qwe>
    <value>-</value>
  </qwe>
  <qwe>
    <value>30</value>
  </qwe>
  <qwe>
    <value>-0</value>
  </qwe>
  <qwe>
    <value/>
  </qwe>
  <qwe>
    <value>8</value>
  </qwe>
</root>

这是我正在尝试使用的XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
<xsl:template match="/">
<html>
<body>
<h2>My qwe Collection</h2>
<xsl:for-each select="root/qwe">
<xsl:variable name="len" select="replace(value,'-','0')" />
<xsl:variable name ="asd" select="sum(//value[number(.)=number(.)])"/>
sum: <xsl:value-of select="$asd"/><br/>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

预期结果:

sum:59

2 个答案:

答案 0 :(得分:2)

这就是你如何做到的。你走在正确的轨道上,使用两个变量是一个很好的方法。

虽然您在样式表中进行了替换并将它们存储在变量$len中 - 但您没有使用此变量。这不会以任何方式影响实际的value元素,即不会对它们执行替换。

请注意,如果您未向我们展示的数据包含其他类型的数字(或者更确切地说,如果您的XML包含您想要考虑的负数),则必须再次修改解决方案。

<强>样式表

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes"/>
<xsl:variable name="values" select="//value"/>         

<xsl:template match="/">
     <xsl:variable name="summands">
       <xsl:for-each select="$values">
          <xsl:element name="summand">
             <xsl:choose>
                <xsl:when test="contains(.,'-') or not(./text())">
                      <xsl:value-of select="0"/>
                </xsl:when>
                <xsl:when test="contains(.,'+')">
                   <xsl:value-of select="substring-after(.,'+')"/>
                </xsl:when>
                <xsl:otherwise>
                      <xsl:value-of select="."/>
                </xsl:otherwise>
             </xsl:choose>
          </xsl:element>
       </xsl:for-each>
     </xsl:variable>

     <xsl:text>SUM: </xsl:text>
     <xsl:value-of select="sum($summands/*)"/>
</xsl:template>

</xsl:stylesheet>

这会产生以下输出

<?xml version="1.0" encoding="UTF-8"?>SUM: 59

答案 1 :(得分:2)

我有点困惑,因为你现有的总和表达式应该有用(唯一的问题是你在 xsl:for-each 循环中而不是在它之后)。

<xsl:value-of select="sum(//value[number(.)=number(.)])"/>

尽管如此,我尝试了两种不同的XSLT处理器,其中一种返回58(大概是因为“+1”未通过数字检查)。

但是你正在使用XSLT 2.0(希望如此),那么这个表达式应该可行,并且更加健壮

<xsl:value-of select="sum(//value
                            [number(translate(.,'-+','0')) = number(translate(.,'-+','0'))]
                            /xs:decimal(translate(.,'-+','0')))"/>

此处的“翻译”会将-替换为0并完全删除+

请注意,您必须将“xs”的命名空间声明为“http://www.w3.org/2001/XMLSchema

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:template match="/">
<html>
<body>
sum: <xsl:value-of select="sum(//value
                                [number(translate(.,'-+','0')) = number(translate(.,'-+','0'))]
                                /xs:decimal(translate(.,'-+','0')))"/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>