title: XSLT 1.0 help with recursion logic
body: <p>I'm having troubles with the logic and would apprecite any help/tips.</p>
  
  <p>I have <code>&lt;Deposits&gt;</code> elements and <code>&lt;Receipts&gt;</code> elements. However there isn't any identification what receipt was paid toward what deposit.</p>
  
  <p>I am trying to update the <code>&lt;Deposits&gt;</code> elements with the following attributes: <br/></p>
  
  <ul>
  <li>@DueAmont - the amount that is still due to pay</li>
  <li>@Status - whether it's paid, outstanding (partly paid) or due</li>
  <li>@ReceiptDate - the latest receipt's date that was paid towards this deposit</li>
  </ul>
  
  <p>Every deposit could be paid with one or more receipts. It also could happen, that 1 receipt could cover one or more deposits. For example. If there are 3 deposits:</p>
  
  <ol>
  <li>500</li>
  <li>100</li>
  <li>450</li>
  </ol>
  
  <p>That are paid with the following receipts:</p>
  
  <ol>
  <li>200</li>
  <li>100</li>
  <li>250 </li>
  </ol>
  
  <p>I want to get the following info:<br/>
  <strong>Deposit 1</strong> is fully paid (status=paid, dueAmount=0, receiptNum=3.<br/>
  <strong>Deposit 2</strong> is partly paid (status=outstanding, dueAmount=50, receiptNum=3.<br/>
  <strong>Deposit 3</strong> is not paid (status=due, dueAmount=450, receiptNum=NAN.<br/></p>
  
  <p><br/><br/>
  <strong>Actual XML:</strong><br/></p>
  
  <pre><code> &lt;Deposits DepositDate="2010-04-07T00:00:00" DepositTotalAmount="500.0000" NoOfPeople="10.0000" PerPerson="50.00"/&gt;
   &lt;Deposits DepositDate="2010-04-12T00:00:00" DepositTotalAmount="100.0000" NoOfPeople="10.0000" PerPerson="10.00"/&gt;
   &lt;Deposits DepositDate="2010-04-26T00:00:00" DepositTotalAmount="450.0000" NoOfPeople="10.0000" PerPerson="45.00"/&gt;
  </code></pre>
  
  <p><br/><br/></p>
  
  <pre><code>&lt;Receipts Amount="200.00" PaymentType="Cheque" Comment="" ReceiptAmount="200.00" ActionDate="2010-04-07T11:01:47" PayingInSlipNumber="" IsCard="No" IsRefund="No"/&gt;
  &lt;Receipts Amount="100.00" PaymentType="Cheque" Comment="" ReceiptAmount="100.00" ActionDate="2010-04-11T11:01:47" PayingInSlipNumber="" IsCard="No" IsRefund="No"/&gt;
  &lt;Receipts Amount="250.00" PaymentType="Cheque" Comment="" ReceiptAmount="250.00" ActionDate="2010-04-20T11:01:47" PayingInSlipNumber="" IsCard="No" IsRefund="No"/&gt;
  </code></pre>
  
  <p>I've added comments in the code explaining what I'm trying to do. I am staring at this code for the 3rd day now non stop - can't see what I'm doing wrong. Please could anyone help me with it? :)</p>
  
  <p>Thanks!</p>
  
  <p><strong>Set up:</strong> <br/>
  $deposits - All the available deposits <br/>
  $receiptsAsc - All the available receipts sorted by their @ActionDate</p>
  
  <p><strong>Code:</strong></p>
  
  <pre><code>&lt;!-- Accumulate all the deposits with @Status, @DueAmount and @ReceiptDate attributes Provide all deposits, receipts and start with 1st receipt --&gt;
  &lt;xsl:variable name="depositsClassified"&gt;
      &lt;xsl:call-template name="classifyDeposits"&gt;
          &lt;xsl:with-param name="depositsAll" select="$deposits"/&gt;
          &lt;xsl:with-param name="receiptsAll" select="$receiptsAsc"/&gt;
          &lt;xsl:with-param name="receiptCount" select="'1'"/&gt;
      &lt;/xsl:call-template&gt;
  &lt;/xsl:variable&gt;
  
  &lt;!-- Recursive function to associate deposits' total amounts with overall receipts paid
      to determine whether a deposit is due, outstanding or paid. Also determine what's the due amount and latest receipt towards the deposit for each deposit --&gt;
  &lt;xsl:template name="classifyDeposits"&gt;
      &lt;xsl:param name="depositsAll"/&gt;
      &lt;xsl:param name="receiptsAll"/&gt;
      &lt;xsl:param name="receiptCount"/&gt;
  
      &lt;!-- If there are deposits to proceed --&gt;
      &lt;xsl:if test="$depositsAll"&gt;
          &lt;!-- Get the 1st deposit --&gt;
          &lt;xsl:variable name="deposit" select="$depositsAll[1]"/&gt;
          &lt;!-- Calculate the sum of all receipts up to and including currenly considered --&gt;
          &lt;xsl:variable name="receiptSum"&gt;
              &lt;xsl:choose&gt;
                  &lt;xsl:when test="$receiptsAll"&gt;
                      &lt;xsl:value-of select="sum($receiptsAll[position() &amp;lt;= $receiptCount]/@ReceiptAmount)"/&gt;
                  &lt;/xsl:when&gt;
                  &lt;xsl:otherwise&gt;0&lt;/xsl:otherwise&gt;
              &lt;/xsl:choose&gt;
          &lt;/xsl:variable&gt;
          &lt;!-- Difference between deposit amount and sum of the receipts calculated
          above --&gt;
          &lt;xsl:variable name="diff" select="$deposit/@DepositTotalAmount - $receiptSum"/&gt;
  
          &lt;xsl:choose&gt;
              &lt;!-- Deposit isn't paid fully and there are more receipts/payments exist.
              So consider the same deposit, but take next receipt into calculation as
              well --&gt;
              &lt;xsl:when test="($diff &amp;gt; 0) and ($receiptCount &amp;lt; count($receiptsAll))"&gt;
                  &lt;xsl:call-template name="classifyDeposits"&gt;
                      &lt;xsl:with-param name="depositsAll" select="$depositsAll"/&gt;
                      &lt;xsl:with-param name="receiptsAll" select="$receiptsAll"/&gt;
                      &lt;xsl:with-param name="receiptCount" select="$receiptCount + 1"/&gt;
                  &lt;/xsl:call-template&gt;
              &lt;/xsl:when&gt;
              &lt;!-- Deposit is paid or we ran out of receipts --&gt;
              &lt;xsl:otherwise&gt;
                  &lt;!-- process the deposit. Determine its status and then update
                  corresponding attributes --&gt;
                  &lt;xsl:apply-templates select="$deposit" mode="defineDeposit"&gt;
                      &lt;xsl:with-param name="diff" select="$diff"/&gt;
                      &lt;xsl:with-param name="receiptNum" select="$receiptCount"/&gt;
                  &lt;/xsl:apply-templates&gt;
  
                  &lt;!-- Recursively call the template with the rest of deposits excluding the first. Before hand update the @ReceiptsAmount. For the receipts before current it is now 0, for the current is what left in the $diff, and simply copy over receipts after current one. --&gt;
                  &lt;xsl:variable name="receiptsUpdatedRTF"&gt;
                      &lt;xsl:for-each select="$receiptsAll"&gt;
                          &lt;xsl:choose&gt;
                              &lt;!-- these receipts was fully accounted for the current deposit. Make them 0 --&gt;
                              &lt;xsl:when test="position() &amp;lt; $receiptCount"&gt;
                                  &lt;xsl:copy&gt;
                                      &lt;xsl:copy-of select="./@*"/&gt;
                                      &lt;xsl:attribute name="ReceiptAmount"&gt;0&lt;/xsl:attribute&gt;
                                  &lt;/xsl:copy&gt;
                              &lt;/xsl:when&gt;
                              &lt;!-- this receipt was partly/fully(in case $diff=0) accounted for the current deposit. Make it whatever is in $diff --&gt;
                              &lt;xsl:when test="position() = $receiptCount"&gt;
                                  &lt;xsl:copy&gt;
                                      &lt;xsl:copy-of select="./@*"/&gt;
                                      &lt;xsl:attribute name="ReceiptAmount"&gt;
                                          &lt;xsl:value-of select="format-number($diff, '#.00;#.00')"/&gt;
                                      &lt;/xsl:attribute&gt;
                                  &lt;/xsl:copy&gt;
                              &lt;/xsl:when&gt;
                              &lt;!-- these receipts weren't yet considered - copy them over --&gt;
                              &lt;xsl:otherwise&gt;
                                  &lt;xsl:copy-of select="."/&gt;
                              &lt;/xsl:otherwise&gt;
                          &lt;/xsl:choose&gt;
                      &lt;/xsl:for-each&gt;
                  &lt;/xsl:variable&gt;
                  &lt;xsl:variable name="receiptsUpdated" select="msxsl:node-set($receiptsUpdatedRTF)/Receipts"/&gt;
  
                  &lt;!-- Recursive call for the next deposit. Starting counting receipts from the current one. --&gt;
                  &lt;xsl:call-template name="classifyDeposits"&gt;
                      &lt;xsl:with-param name="depositsAll" select="$deposits[position() != 1]"/&gt;
                      &lt;xsl:with-param name="receiptsAll" select="$receiptsUpdated"/&gt;
                      &lt;xsl:with-param name="receiptCount" select="$receiptCount"/&gt;
                  &lt;/xsl:call-template&gt;
              &lt;/xsl:otherwise&gt;
          &lt;/xsl:choose&gt;
      &lt;/xsl:if&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Determine deposit's status and due amount --&gt;
  &lt;xsl:template match="MultiDeposits" mode="defineDeposit"&gt;
      &lt;xsl:param name="diff"/&gt;
      &lt;xsl:param name="receiptNum"/&gt;
  
      &lt;xsl:choose&gt;
          &lt;xsl:when test="$diff &amp;lt;= 0"&gt;
              &lt;xsl:apply-templates select="." mode="addAttrs"&gt;
                  &lt;xsl:with-param name="status" select="'paid'"/&gt;
                  &lt;xsl:with-param name="dueAmount" select="'0'"/&gt;
                  &lt;xsl:with-param name="receiptNum" select="$receiptNum"/&gt;
              &lt;/xsl:apply-templates&gt;
          &lt;/xsl:when&gt;
          &lt;xsl:when test="$diff = ./@DepositTotalAmount"&gt;
              &lt;xsl:apply-templates select="." mode="addAttrs"&gt;
                  &lt;xsl:with-param name="status" select="'due'"/&gt;
                  &lt;xsl:with-param name="dueAmount" select="$diff"/&gt;
              &lt;/xsl:apply-templates&gt;
          &lt;/xsl:when&gt;
          &lt;xsl:when test="$diff &amp;lt; ./@DepositTotalAmount"&gt;
              &lt;xsl:apply-templates select="." mode="addAttrs"&gt;
                  &lt;xsl:with-param name="status" select="'outstanding'"/&gt;
                  &lt;xsl:with-param name="dueAmount" select="$diff"/&gt;
                  &lt;xsl:with-param name="receiptNum" select="$receiptNum"/&gt;
              &lt;/xsl:apply-templates&gt;
          &lt;/xsl:when&gt;
          &lt;xsl:otherwise/&gt;
      &lt;/xsl:choose&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Add new attributes (@Status, @DueAmount and @ReceiptDate) to the 
      deposit element --&gt;
  &lt;xsl:template match="MultiDeposits" mode="addAttrs"&gt;
      &lt;xsl:param name="status"/&gt;
      &lt;xsl:param name="dueAmount"/&gt;
      &lt;xsl:param name="receiptNum" select="''"/&gt;
  
      &lt;xsl:copy&gt;
          &lt;xsl:copy-of select="./@*"/&gt;
          &lt;xsl:attribute name="Status"&gt;&lt;xsl:value-of select="$status"/&gt;&lt;/xsl:attribute&gt;
          &lt;xsl:attribute name="DueAmount"&gt;&lt;xsl:value-of select="$dueAmount"/&gt;&lt;/xsl:attribute&gt;
          &lt;xsl:if test="$receiptNum != ''"&gt;
              &lt;xsl:attribute name="ReceiptDate"&gt;
                  &lt;xsl:value-of select="$receiptsAsc[position() = $receiptNum]/@ActionDate"/&gt;
              &lt;/xsl:attribute&gt;
          &lt;/xsl:if&gt;
          &lt;xsl:copy-of select="./*"/&gt;
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  </code></pre>