XSLT高级数学



请帮助我使用XSLT中的数学。我需要总计具有相同unit_id的增值税字段。

输入XML:

 <Root> 
<RowSet>
            <unit_id>1<unit_id>
            <price>100<unit_id>
            <VAT>2<VAT> 
</RowSet> 
<RowSet>
            <unit_id>1<unit_id>
            <price>200<unit_id>
            <VAT>3<VAT> 
</RowSet> 
<RowSet>
            <unit_id>2<unit_id>
            <price>300<unit_id>
            <VAT>4<VAT> 
</RowSet>
 </Root>

预期输出必须是这样的:

<Root>
<Output>
        <unit_id>1<unit_id>
        <total>800<total> <?-(100*2+200*3)-?>
</Output>
<Output>
        <unit_id>2<unit_id>
        <total>1200<total>  <?-(300*4)-?>
</Output>
</Root>

我在仪式周期中尝试了总和(价格*增值税),但没有帮助。

我试图使用以下方式:

<Root>
<xsl:variable name="ID">
<xsl:value-of select="unit_id"/>
</xsl:variable>                   
<xsl:for-each select="/Root/RowSet[unit_id = $ID]">
<Output>
<xsl:if test="position() = count (/Root/RowSet[unit_id = $ID])">
<total>
<xsl:value-of select="sum(/Root/RowSet[unit_id = $ID]/price * /Root/RowSet[unit_id = $ID]/VAT)"/>
</total>
</xsl:if>
</Output>
</Root>

错误的输出是:

   <Root>
    <Output>
            <unit_id>1<unit_id>
            <total>200<total> <?-(100*2)-?>
    </Output>
    <Output>
            <unit_id>2<unit_id>
            <total>1200<total>  <?-(300*4)-?>
    </Output>
    </Root>

运行总计是XSLT中的常见问题。递归是解决该问题的方法。(这不是XSLT唯一的 - 任何没有可变变量的语言可以正常工作。)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <Root>
      <xsl:apply-templates select="Root/RowSet" />
    </Root>
  </xsl:template>
  <xsl:template match="RowSet">
    <!-- only do work for the *first* RowSet with any particular ID -->
    <xsl:if test="not(preceding-sibling::RowSet/unit_id = current()/unit_id)">
      <Output>
        <xsl:copy-of select="unit_id" />
        <total>
          <xsl:call-template name="running-total">
            <xsl:with-param name="values" select="/Root/RowSet[
              unit_id = current()/unit_id
            ]" />
          </xsl:call-template>
        </total>
      </Output>
    </xsl:if>
  </xsl:template>
  <xsl:template name="running-total">
    <xsl:param name="values" />
    <xsl:choose>
      <xsl:when test="count($values)">
        <xsl:variable name="curr" select="$values[1]" />
        <xsl:variable name="rest" select="$values[position() &gt; 1]" />
        <!-- recursive step: calculate the total of all remaining values -->
        <xsl:variable name="subtotal">
          <xsl:call-template name="running-total">
            <xsl:with-param name="values" select="$rest" />
          </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="$subtotal + $curr/price * $curr/VAT" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="0" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

请参阅http://www.xmlplayground.com/nf7d2o

笔记

<xsl:if test="not(preceding-sibling::RowSet/unit_id = current()/unit_id)">是分组数据的一种方式。这样做的更高级的方法称为穆恩式分组,但为了这个答案,我不想进入。

running-total模板在JavaScript中看起来像这样:

function runningTotal(values) {
  if (values.length) {
    var curr = values.pop();              // pop() shortens values array by one
    var subtotal = runningTotal(values);  // recurses over remaining values
    return subtotal + curr.price * curr.VAT;
  } else {
    return 0;
  }
}

这是一个非恢复的,两个 - 通过解决方案

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kRSByUId" match="RowSet" use="unit_id"/>
 <xsl:variable name="vrtfPass1"><xsl:apply-templates/></xsl:variable>
 <xsl:template match="node()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>
 <xsl:template match="/">
  <xsl:apply-templates mode="pass2" select="ext:node-set($vrtfPass1)/*"/> 
 </xsl:template>
 <xsl:template mode="pass2" match="/*">
  <Root>
   <xsl:apply-templates mode="pass2" select=
    "RowSet[generate-id()
           =
            generate-id(key('kRSByUId', unit_id)[1])]"/>
  </Root>
 </xsl:template>
 <xsl:template mode="pass2" match="RowSet">
  <RowSet>
   <xsl:copy-of select="unit_id"/>
   <total>
     <xsl:value-of select="sum(key('kRSByUId', unit_id)/subTotal)"/>
   </total>
  </RowSet>
 </xsl:template>
 <xsl:template match="RowSet/price">
  <subTotal><xsl:value-of select=". * ../VAT"/></subTotal>
 </xsl:template>
 <xsl:template match="VAT"/>
</xsl:stylesheet>

将此转换应用于提供的XML文档(严重的畸形纠正):

<Root>
    <RowSet>
        <unit_id>1</unit_id>
        <price>100</price>
        <VAT>2</VAT>
    </RowSet>
    <RowSet>
        <unit_id>1</unit_id>
        <price>200</price>
        <VAT>3</VAT>
    </RowSet>
    <RowSet>
        <unit_id>2</unit_id>
        <price>300</price>
        <VAT>4</VAT>
    </RowSet>
</Root>

想要的,正确的结果

<Root>
   <RowSet>
      <unit_id>1</unit_id>
      <total>800</total>
   </RowSet>
   <RowSet>
      <unit_id>2</unit_id>
      <total>1200</total>
   </RowSet>
</Root>

说明

  1. 在第一个通过中,我们将源XML文档转换为:

<Root>
   <RowSet>
      <unit_id>1</unit_id>
      <subTotal>200</subTotal>
   </RowSet>
   <RowSet>
      <unit_id>1</unit_id>
      <subTotal>600</subTotal>
   </RowSet>
   <RowSet>
      <unit_id>2</unit_id>
      <subTotal>1200</subTotal>
   </RowSet>
</Root>

.2。在第二次通过中,我们执行经典的Muenchian分组,并在每个组中总结subTotal儿童并产生total元素,其文本节点子是如此计算的总和。

相关内容

  • 没有找到相关文章

最新更新