Note that there are some explanatory texts on larger screens.

plurals
  1. POXSLT 1.0 help with recursion logic
    primarykey
    data
    text
    <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>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload