XSL recursion problem

Discussion in 'XML' started by will, Aug 22, 2006.

  1. will

    will Guest

    All

    Hope you can help with the following..

    I am using recursion to calculate the sum of
    DEBT_INPUT_VALUE_BEFORE_SPLIT * CTXR_TAX_RATE elements, along the lines
    of sum(a*b)

    ie

    xml fragment (the source doc have multiple EXPENSE segments) is as
    follows

    <EXPENSE>
    <TABLE>TCO</TABLE>
    <KEY>15000023955114</KEY>
    <PROCCESSE_DATE>20060328</PROCCESSE_DATE>
    <ITEM_DATE>20060209</ITEM_DATE>
    <SYSTEM_DATE>20060328</SYSTEM_DATE>
    <REFERENCE>L</REFERENCE>
    <SUPPLIER_REFERENCE/>
    <PURCHASE_ORDER_NO/>
    <FILENOTE>67</FILENOTE>
    <UNIT_QUANTITY/>
    <UNIT_VALUE/>
    <FUNCTION_TEXT/>
    <PTK_TASK/>
    <TRX_TYPE>CSEXP</TRX_TYPE>
    <ICC_ICC>PRINT</ICC_ICC>
    <ECODE>E102</ECODE>
    <DEBT_INPUT_VALUE>2.81</DEBT_INPUT_VALUE>
    <DEBT_INPUT_VALUE_BEFORE_SPLIT>6.7</DEBT_INPUT_VALUE_BEFORE_SPLIT>
    <DEBT_OVERRIDE_VALUE>2.81</DEBT_OVERRIDE_VALUE>
    <DEBT_DISCOUNT_VALUE>0.00</DEBT_DISCOUNT_VALUE>
    <ACC_ACTIVITY_CATGRY/>
    <CTXR_TAX_RATE>.175</CTXR_TAX_RATE>
    </EXPENSE>


    xsl i'm using is a single call to


    <xsl:variable name="v_split_expense_tax_total">
    <!-- Call to sumItems to sum (EXPENSE/DEBT_INPUT_VALUE_BEFORE_SPLIT
    * EXPENSE/CTXR_TAX_RATE )-->
    <xsl:call-template name="sumExpItems">
    <xsl:with-param name="p_index" select=" '1' "/>
    <xsl:with-param name="p_items" select="//INVOICE"/>
    <xsl:with-param name="p_runningTotal" select=" '0' "/>
    </xsl:call-template>
    </xsl:variable>
    <xsl:template name="sumExpItems">
    <!--Recursive template to sum (EXPENSE/DEBT_INPUT_VALUE_BEFORE_SPLIT
    * EXPENSE/CTXR_TAX_RATE )-->
    <xsl:param name="p_index" select=" '1' "/>
    <xsl:param name="p_items"/>
    <xsl:param name="p_runningTotal" select=" '0' "/>
    <xsl:variable name="v_current_item"
    select="$p_items/EXPENSE[$p_index]/DEBT_INPUT_VALUE_BEFORE_SPLIT *
    $p_items/EXPENSE[$p_index]/CTXR_TAX_RATE"/>
    <xsl:variable name="v_remainingItems">
    <xsl:choose>
    <!--xsl:when test="$p_index = 4000"-->
    <xsl:when test="$p_index = count($p_items/EXPENSE)">
    <!--When index = count of expense items in bill ie at last item
    -->
    <xsl:text>0</xsl:text>
    </xsl:when>
    <xsl:eek:therwise>
    <xsl:call-template name="sumExpItems">
    <xsl:with-param name="p_index" select="$p_index+1"/>
    <xsl:with-param name="p_items" select="$p_items"/>
    <xsl:with-param name="p_runningTotal" select="$p_runningTotal +
    $v_current_item"/>
    </xsl:call-template>
    </xsl:eek:therwise>
    </xsl:choose>
    </xsl:variable>
    <xsl:value-of select="$v_current_item +$v_remainingItems"/>
    </xsl:template>


    This works when i have about 100 expense items

    However my source xml has more than 4000 items and i am getting "The
    XSL stack has overflowed - probable cause is infinite template
    recursion.."

    I'm pretty sure the recursive template does not loop infinitely as it
    has an exit clause when it reaches the last EXPENSE element.

    I'm using MSXML4 from xmlSpy

    Anyone know

    a) Is there an upper limit on number of recursion before the processor
    secides its in an infinite loop.

    b) can the above be made more efficient

    c) any other i can get round the above..

    Thanks in advance..

    Will
    will, Aug 22, 2006
    #1
    1. Advertising

  2. I don't know enough about MSXSL to be able to advise you on whether its
    limit can be reset. However, in the "other ideas" category:

    A non-recursive solution would be to gather all the a*b values in a
    temporary document tree, and then call sum() on the result.
    Unfortunately in XSLT 1.0 you'll need to use the EXSLT node-set
    extension function to convert the result tree fragment into a form that
    can be processed further, but that's a fairly standard nuisance.

    Untested fragment just to illustrate the concept:

    <xsl:variable name="products">
    <xsl:for-each "//expense">
    <product><xsl:value-of select="DEBT_INPUT_VALUE_BEFORE_SPLIT *
    CTXR_TAX_RATE"/></product>
    </xsl:for-each>
    </xsl:variable>

    The calculated sum-of-products is:
    <xsl:value-of select="sum(exslt:node-set($products)/product)"/>
    Joseph Kesselman, Aug 22, 2006
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kevin Flood
    Replies:
    0
    Views:
    1,002
    Kevin Flood
    Sep 8, 2004
  2. Kevin Flood
    Replies:
    1
    Views:
    2,702
    Kevin Flood
    Sep 13, 2004
  3. Klaus Friese
    Replies:
    0
    Views:
    451
    Klaus Friese
    Nov 22, 2004
  4. Replies:
    1
    Views:
    3,568
    A. Bolmarcich
    May 27, 2005
  5. Replies:
    8
    Views:
    709
    John Reye
    Apr 26, 2012
Loading...

Share This Page