基于变量信息对XSLT中的节点进行分组

时间:2017-01-12 09:58:30

标签: xml xslt-2.0

我在找出分组金额的方法时遇到了问题。我需要做两种方法。

-I-。第一种方法是指我没有多个费用的情况。   (这个完成了)。输入xml信息。

        <ListOfAFGFINSApplicationIncomeandExpensesFormFill>
          <AFGFINSApplicationIncomeandExpenses>
              <AFGSubCategory>Rental Expense</AFGSubCategory>
              <Amount>2000</Amount>
              <Frequency>Quarterly</Frequency>
           </AFGFINSApplicationIncomeandExpenses>

          <AFGFINSApplicationIncomeandExpenses>
                <AFGSubCategory>Child Maintenance Paid</AFGSubCategory>
                <Amount>1000</Amount>
                <Frequency>4 Weekly</Frequency>                    
          </AFGFINSApplicationIncomeandExpenses>

         </ListOfAFGFINSApplicationIncomeandExpensesFormFill>

我正在使用这个xslt代码:

<xsl:template match="ListOfAFGFINSApplicationIncomeandExpensesFormFill/AFGFINSApplicationIncomeandExpenses
    [AFGSubCategory = ('Child Maintenance Paid', 'Rental Expense')]" mode="OtherCommitment">

    <OtherCommitment 
        UniqueID="{fn:UniqueID(Id)}">

        <xsl:attribute name="Amount">
            <xsl:apply-templates select="." mode="Amount"/>
        </xsl:attribute>

        <xsl:attribute name="Frequency" select="fn:IncomeFrequency(Frequency)"/>

        <xsl:attribute name="Category">
            <xsl:choose>
                <xsl:when test="AFGSubCategory = 'Child Maintenance Paid'">Child Maintenance</xsl:when>
                <xsl:when test="AFGSubCategory = 'Rental Expense'">Rent</xsl:when>
            </xsl:choose>
        </xsl:attribute>

    </OtherCommitment>

使用以下模板计算金额:

    <xsl:template match="node()" mode="Amount">
    <xsl:choose>
        <xsl:when test="Frequency = '4 Weekly'">
            <xsl:value-of select="(Amount * 13) div 12"/>
        </xsl:when>
        <xsl:when test="Frequency = 'Quarterly'">
            <xsl:value-of select="Amount * 4"/>
        </xsl:when>
        <xsl:when test="Frequency != ''">
            <xsl:value-of select="Amount"/>
        </xsl:when>
    </xsl:choose>
</xsl:template>

对于我正在使用的频率:

<xsl:function name="fn:IncomeFrequency">
    <xsl:param name="Frequency"/>
    <xsl:choose>
        <xsl:when test="$Frequency = '4 Weekly'">Monthly</xsl:when>
        <xsl:when test="$Frequency = 'Annually'">Yearly</xsl:when>
        <xsl:when test="$Frequency = 'Quarterly'">Yearly</xsl:when>
        <xsl:when test="$Frequency != ''">
            <xsl:value-of select="$Frequency"/>
        </xsl:when>
        <xsl:when test="$Frequency/../AFGAnnualAmount != ''">Yearly</xsl:when>
    </xsl:choose>
</xsl:function>

这是输出,对于这种情况是正确的:

         <OtherCommitment Amount="8000" Frequency="Yearly" 
              Category="Rent">
         </OtherCommitment>
         <OtherCommitment Amount="1083.3333333333333"
                            Frequency="Monthly"
                            Category="Child Maintenance">
         </OtherCommitment>

-II-第二种情况是我有一个同名的SubCategory,我需要将频率转换为'Monthly'值。
输入示例:

       <ListOfAFGFINSApplicationIncomeandExpensesFormFill>
          <AFGFINSApplicationIncomeandExpenses>
              <AFGSubCategory>Rental Expense</AFGSubCategory>
              <Amount>2000</Amount>
              <Frequency>Quarterly</Frequency>
           </AFGFINSApplicationIncomeandExpenses>

           <AFGFINSApplicationIncomeandExpenses>
              <AFGSubCategory>Rental Expense</AFGSubCategory>
              <Amount>1000</Amount>
              <Frequency>Mounthly</Frequency>
           </AFGFINSApplicationIncomeandExpenses>

          <AFGFINSApplicationIncomeandExpenses>
                <AFGSubCategory>Child Maintenance Paid</AFGSubCategory>
                <Amount>1000</Amount>
                <Frequency>4 Weekly</Frequency>                    
          </AFGFINSApplicationIncomeandExpenses>

         </ListOfAFGFINSApplicationIncomeandExpensesFormFill>

输出需要成为。

     <OtherCommitment Amount="1666.6666666666667" Frequency="Monthly" 
          Category="Rent">
     </OtherCommitment>
    <!-- This will keep the first approach because is only one 'Child Maintenance'--> 
    <OtherCommitment Amount="1083.3333333333333"
                        Frequency="Monthly"
                        Category="Child Maintenance">
     </OtherCommitment>

计算我在这种情况下需要使用的金额可能是:

<xsl:template match="node()" mode="AmountMonthly">
    <xsl:choose>
        <xsl:when test="Frequency = 'Weekly'">
            <xsl:value-of select="fn:remove-scientific-notation((Amount * 52) div 12)"/>
        </xsl:when>
        <xsl:when test="Frequency = 'Fortnightly'">
            <xsl:value-of select="fn:remove-scientific-notation((Amount * 26) div 12)"/>
        </xsl:when>
        <xsl:when test="Frequency = '4 Weekly'">
            <xsl:value-of select="fn:remove-scientific-notation((Amount * 13) div 12)"/>
        </xsl:when>
        <xsl:when test="Frequency = 'Monthly'">
            <xsl:value-of select="Amount"/>
        </xsl:when>
        <xsl:when test="Frequency = 'Quarterly'">
            <xsl:value-of select="fn:remove-scientific-notation((Amount * 4) div 12)"/>
        </xsl:when>
        <xsl:when test="Frequency = 'Annually'">
            <xsl:value-of select="fn:remove-scientific-notation(Amount div 12)"/>
        </xsl:when>
    </xsl:choose>
</xsl:template>

但我无法搞清楚,如何总结开支。

1 个答案:

答案 0 :(得分:0)

您已将其标记为XSLT 2.0,因此当然要按类别使用xsl:for-each-group group-by进行分组。我有一个小例子来处理金额,我希望你可以将它集成到你现有的代码中:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xmlns:mf="http://example.com/mf" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs mf">


    <xsl:function name="mf:monthlyAmount" as="xs:decimal">
        <xsl:param name="amountEl" as="element(AFGFINSApplicationIncomeandExpenses)"/>
        <xsl:variable name="amount" as="xs:decimal" select="xs:decimal($amountEl/Amount)"/>
        <xsl:sequence select="if ($amountEl/Frequency = 'Weekly')
                              then $amount * 52 div 12
                              else if ($amountEl/Frequency = 'Quarterly')
                              then $amount * 4 div 12
                              else if ($amountEl/Frequency = 'Monthly')
                              then $amount
                              else 0"/>
    </xsl:function>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ListOfAFGFINSApplicationIncomeandExpensesFormFill">
        <xsl:for-each-group select="AFGFINSApplicationIncomeandExpenses" group-by="AFGSubCategory">
            <OtherCommitment Amount="{sum(for $item in current-group() return mf:monthlyAmount($item))}"/>
        </xsl:for-each-group>
    </xsl:template>
</xsl:transform>

转换

<ListOfAFGFINSApplicationIncomeandExpensesFormFill>
          <AFGFINSApplicationIncomeandExpenses>
              <AFGSubCategory>Rental Expense</AFGSubCategory>
              <Amount>2000</Amount>
              <Frequency>Quarterly</Frequency>
           </AFGFINSApplicationIncomeandExpenses>

           <AFGFINSApplicationIncomeandExpenses>
              <AFGSubCategory>Rental Expense</AFGSubCategory>
              <Amount>1000</Amount>
              <Frequency>Monthly</Frequency>
           </AFGFINSApplicationIncomeandExpenses>

          <AFGFINSApplicationIncomeandExpenses>
                <AFGSubCategory>Child Maintenance Paid</AFGSubCategory>
                <Amount>1000</Amount>
                <Frequency>4 Weekly</Frequency>                    
          </AFGFINSApplicationIncomeandExpenses>

         </ListOfAFGFINSApplicationIncomeandExpensesFormFill>

<OtherCommitment Amount="1666.666666666666666667"/><OtherCommitment Amount="0"/>

所以我认为对于第一组计算是正确的,你需要添加其他属性,你需要为各种数量类型添加其他计算。

示例在http://xsltransform.net/3NSSEvq上线。