[xsl] MSXML4 dom crash?

Subject: [xsl] MSXML4 dom crash?
From: "Macaulay,Malcolm (US)" <Malcolm.Macaulay2@xxxxxxxxx>
Date: Thu, 1 Aug 2002 09:44:38 -0500
Has anyone had any experience with the MSXML4 DOM intermittently crashing during a transformation? I'm observing the following:

*	transforms works intermittently in XMLSpy (using MSXML4) - XMLSpy error message is something like "not enough resources to complete this operation"
*	After the first XMLSpy crash as above, the next attempt gives a fatal XMLSpy crash
*	transforms work 100% when XSLT is referenced as a process instruction and XML is opened in IE6
*	transform works intermittently using MSXML4 via VBA code.

My XLST and XML are attached below. As a background, the XML is created in a generic way from an input dialog in Excel. The purpose of the XSLT is to transform this generic XML into the format required by an XML-based analysis package (the XML stores an insurance triangle of aggregated losses). 

The XLST uses recursion but the stack will be small due to the dimensions of the triangle. Please note: I'm tied to using MSXML4 and I'm using the microsoft node-set() function (which has never given me any grief before..).

Can anyone shed any light on this problem? 

Thanks in advance.

cheers

Malcolm

XML:

<RawData>
	<Row row="10">
		<Treaty_Year cell="$B$10">1991</Treaty_Year>
		<mth_18 cell="$D$10">627513</mth_18>
		<mth_30 cell="$E$10">1165685</mth_30>
		<mth_42 cell="$F$10">783021</mth_42>
		<mth_54 cell="$G$10">814978</mth_54>
		<mth_66 cell="$H$10">863484</mth_66>
		<mth_78 cell="$I$10">845860</mth_78>
		<mth_90 cell="$J$10">835660</mth_90>
		<mth_102 cell="$K$10">835660</mth_102>
		<mth_114 cell="$L$10">835660</mth_114>
		<mth_126 cell="$M$10">835660</mth_126>
	</Row>
	<Row row="11">
		<Treaty_Year cell="$B$11">1992</Treaty_Year>
		<mth_6 cell="$C$11">236642</mth_6>
		<mth_18 cell="$D$11">2195816</mth_18>
		<mth_30 cell="$E$11">2592762</mth_30>
		<mth_42 cell="$F$11">2457251</mth_42>
		<mth_54 cell="$G$11">2043993</mth_54>
		<mth_66 cell="$H$11">2004121</mth_66>
		<mth_78 cell="$I$11">2002983</mth_78>
		<mth_90 cell="$J$11">1893751</mth_90>
		<mth_102 cell="$K$11">1900753</mth_102>
		<mth_114 cell="$L$11">1973989</mth_114>
	</Row>
	<Row row="12">
		<Treaty_Year cell="$B$12">1993</Treaty_Year>
		<mth_6 cell="$C$12">986921</mth_6>
		<mth_18 cell="$D$12">2614979</mth_18>
		<mth_30 cell="$E$12">3000810</mth_30>
		<mth_42 cell="$F$12">3265298</mth_42>
		<mth_54 cell="$G$12">3107803</mth_54>
		<mth_66 cell="$H$12">3319679</mth_66>
		<mth_78 cell="$I$12">3269484</mth_78>
		<mth_90 cell="$J$12">3058111</mth_90>
		<mth_102 cell="$K$12">3194808</mth_102>
	</Row>
	<Row row="13">
		<Treaty_Year cell="$B$13">1994</Treaty_Year>
		<mth_6 cell="$C$13">710650</mth_6>
		<mth_18 cell="$D$13">1343807</mth_18>
		<mth_30 cell="$E$13">2189145</mth_30>
		<mth_42 cell="$F$13">2308186</mth_42>
		<mth_54 cell="$G$13">2465973</mth_54>
		<mth_66 cell="$H$13">2568565</mth_66>
		<mth_78 cell="$I$13">2572140</mth_78>
		<mth_90 cell="$J$13">2611738</mth_90>
	</Row>
	<Row row="14">
		<Treaty_Year cell="$B$14">1995</Treaty_Year>
		<mth_6 cell="$C$14">553471</mth_6>
		<mth_18 cell="$D$14">1400592</mth_18>
		<mth_30 cell="$E$14">2322491</mth_30>
		<mth_42 cell="$F$14">2460961</mth_42>
		<mth_54 cell="$G$14">2902364</mth_54>
		<mth_66 cell="$H$14">2777420</mth_66>
		<mth_78 cell="$I$14">2872115</mth_78>
	</Row>
	<Row row="15">
		<Treaty_Year cell="$B$15">1996</Treaty_Year>
		<mth_6 cell="$C$15">241839</mth_6>
		<mth_18 cell="$D$15">1766116</mth_18>
		<mth_30 cell="$E$15">2591168</mth_30>
		<mth_42 cell="$F$15">2715182</mth_42>
		<mth_54 cell="$G$15">2870941</mth_54>
		<mth_66 cell="$H$15">2916189</mth_66>
	</Row>
	<Row row="16">
		<Treaty_Year cell="$B$16">1997</Treaty_Year>
		<mth_6 cell="$C$16">360359</mth_6>
		<mth_18 cell="$D$16">1209331</mth_18>
		<mth_30 cell="$E$16">1878517</mth_30>
		<mth_42 cell="$F$16">2672480</mth_42>
		<mth_54 cell="$G$16">3022979</mth_54>
	</Row>
	<Row row="17">
		<Treaty_Year cell="$B$17">1998</Treaty_Year>
		<mth_6 cell="$C$17">264327</mth_6>
		<mth_18 cell="$D$17">1219140</mth_18>
		<mth_30 cell="$E$17">2389356</mth_30>
		<mth_42 cell="$F$17">2847353</mth_42>
	</Row>
	<Row row="18">
		<Treaty_Year cell="$B$18">1999</Treaty_Year>
		<mth_6 cell="$C$18">340482</mth_6>
		<mth_18 cell="$D$18">1392449</mth_18>
		<mth_30 cell="$E$18">2268668</mth_30>
	</Row>
	<Row row="19">
		<Treaty_Year cell="$B$19">2000</Treaty_Year>
		<mth_6 cell="$C$19">288364</mth_6>
		<mth_18 cell="$D$19">1701468</mth_18>
	</Row>
	<Row row="20">
		<Treaty_Year cell="$B$20">2001</Treaty_Year>
		<mth_6 cell="$C$20">705359</mth_6>
	</Row>
	<Row row="21">
		<Treaty_Year cell="$B$21">2002</Treaty_Year>
	</Row>
	<Row row="22">
		<Treaty_Year cell="$B$22">2003</Treaty_Year>
	</Row>
	<Row row="23">
		<Treaty_Year cell="$B$23">2004</Treaty_Year>
	</Row>
	<Row row="24">
		<Treaty_Year cell="$B$24">2005</Treaty_Year>
	</Row>
	<Row row="25">
		<Treaty_Year cell="$B$25">2006</Treaty_Year>
	</Row>
	<Row row="26">
		<Treaty_Year cell="$B$26">2007</Treaty_Year>
	</Row>
	<Row row="27">
		<Treaty_Year cell="$B$27">2008</Treaty_Year>
	</Row>
	<Row row="28">
		<Treaty_Year cell="$B$28">2009</Treaty_Year>
	</Row>
	<Row row="29">
		<Treaty_Year cell="$B$29">2010</Treaty_Year>
		<mth_6 cell="$C$29">340482</mth_6>
	</Row>
</RawData>


XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; xmlns:T="urn:TRns-Triangle" xmlns:AP="urn:TRns-AnalysisPage" xmlns:Cur="urn:TRns-Currency" xmlns:user="http://mycompany.com/mynamespace"; xmlns:msxsl="urn:schemas-microsoft-com:xslt">
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
	<!--
	
	Notes:
	
		- templates assume no non-numerics (these are taken care of by the validation XSLT)
		- templates should be impervious to unknown elements
		
	-->

	<!-- 
	
	Development values keyed by Treaty_Year#Development_Months 	
	-->
	<xsl:key name="cellsByRowYearByDevMths" match="/RawData/Row/*[substring-before(name(),'_') = 'mth']" use="concat(../Treaty_Year , '#' , substring-after(name(),'_'))"/>
	<!--
	
	
	We need to keep the triangle triangular - i.e. the last year row must be equal to the maximum of
	Treaty_Year + count[development periods].
	
	-->
	<xsl:variable name="years" select="/RawData/Row/Treaty_Year"/>
	<!--
	
	Create a temp tree to hold the values of Treaty_year  + count[development periods]
	
	-->
	<xsl:variable name="yearPlusNoOfDevYear">
		<TempTree>
			<xsl:for-each select="/RawData/Row">
				<LastYear>
					<xsl:value-of select="Treaty_Year + count(*[substring-before(name(),'_') = 'mth'])"/>
				</LastYear>
			</xsl:for-each>
		</TempTree>
	</xsl:variable>
	<!--
	
	Create a temp tree to hold the values of development months
	
	-->
	<xsl:variable name="developmentMonthValues">
		<TempTree>
			<xsl:for-each select="/RawData/Row/*[substring-before(name(),'_') = 'mth']">
				<Months>
					<xsl:value-of select="substring-after(name(),'_')"/>
				</Months>
			</xsl:for-each>
		</TempTree>
	</xsl:variable>
	<!--
	
	-->
	<xsl:variable name="maxYear">
		<xsl:call-template name="max">
			<xsl:with-param name="nodes" select="msxsl:node-set($yearPlusNoOfDevYear)/TempTree/LastYear"/>
		</xsl:call-template>
	</xsl:variable>
	<!--
	
	-->
	<xsl:variable name="minYear">
		<xsl:call-template name="min">
			<xsl:with-param name="nodes" select="$years"/>
		</xsl:call-template>
	</xsl:variable>
	<!--
	
	-->
	<xsl:variable name="minMonths">
		<xsl:call-template name="min">
			<xsl:with-param name="nodes" select="msxsl:node-set($developmentMonthValues)/TempTree/Months"/>
		</xsl:call-template>
	</xsl:variable>
	<!--
	
	
	-->
	<xsl:template match="/">
		<!--
		
		Triangle rows are created in temp element as the containing element in the analysis page
		carries attributes which cannot be alterted via the excel dialog.
		
		Note: the ??? attributes are not part of the excel dialog and will be handled by the excel code.

		-->
		<T:Triangle MonthsOfDevInLastDiag="???" MonthsOfDevInFirstColumn="???">
			<!--
			
			Start off the recursive row maker at minYear.
			-->
			<xsl:call-template name="recursiveCreateRows">
				<xsl:with-param name="rowYear" select="$minYear"/>
			</xsl:call-template>
			
			<!-- the empty development element which will be populated by TRUSTRater -->
			<T:CalculatedDFs/>
			
		</T:Triangle>
	</xsl:template>
	<!--
	
	
	-->
	<xsl:template name="recursiveCreateRows">
		<xsl:param name="rowYear"/>
		<xsl:if test="($maxYear + 1) &gt; $rowYear">
			<!--
			
			Call template to get row created for $rowYear
			-->
			<xsl:call-template name="makeRow">
				<xsl:with-param name="rowYear" select="$rowYear"/>
			</xsl:call-template>
			<!--
			
			Recurse to $rowYear + 1
			-->
			<xsl:call-template name="recursiveCreateRows">
				<xsl:with-param name="rowYear" select="number($rowYear) + 1"/>
			</xsl:call-template>
		</xsl:if>
	</xsl:template>
	<!--
	
	Template to create a single row of the triangle
	
	Note: $minYear and $minMonths are global variables
	
	-->
	<xsl:template name="makeRow">
		<xsl:param name="rowYear"/>
		<T:Row Incomplete="0">
			<xsl:attribute name="Year"><xsl:value-of select="$rowYear"/></xsl:attribute>
			<!-- 
			
			Call recursive template which create the development elements within the year. -->
			<xsl:call-template name="recursiveDevElementMaker">
				<xsl:with-param name="rowYear" select="$rowYear"/>
				<xsl:with-param name="currentDevMonths" select="$minMonths"/>
				<xsl:with-param name="currentDevYear" select="$rowYear"/>
				<xsl:with-param name="colNumber">1</xsl:with-param>
			</xsl:call-template>
		</T:Row>
	</xsl:template>
	<!--
	
	
	-->
	<xsl:template name="recursiveDevElementMaker">
		<xsl:param name="rowYear"/>
		<xsl:param name="currentDevMonths"/>
		<xsl:param name="currentDevYear"/>
		<xsl:param name="colNumber"/>
		<!-- 
		
		Note: maxYear is a global variable
		
		-->
		<xsl:if test="($maxYear + 1) &gt; $currentDevYear">
			<T:Dev LinkRatio="">
				<xsl:attribute name="Col"><xsl:value-of select="$colNumber"/></xsl:attribute>
				<xsl:variable name="rawDevElement" select="key('cellsByRowYearByDevMths' , concat($rowYear , '#' , $currentDevMonths))"/>
				<xsl:choose>
					<xsl:when test="$rawDevElement">
						<xsl:value-of select="$rawDevElement"/>
					</xsl:when>
					<xsl:otherwise>0</xsl:otherwise>
				</xsl:choose>
			</T:Dev>
			<!--	
			
			Recurse to the new development period-->
			<xsl:call-template name="recursiveDevElementMaker">
				<xsl:with-param name="rowYear" select="$rowYear"/>
				<xsl:with-param name="currentDevMonths" select="number($currentDevMonths) + 12"/>
				<xsl:with-param name="currentDevYear" select="number($currentDevYear) + 1"/>
				<xsl:with-param name="colNumber" select="number($colNumber) + 1"/>
			</xsl:call-template>
		</xsl:if>
	</xsl:template>
	
	
	
	<!-- 
	
	Common templates which are normally in a separate linked XSLT 
	
	-->
	
	<!--
	
	Min template. Returns minimum numeric value from $nodes. If no numeric nodes or no nodes then it
	returns $defaultValue
	-->
	<xsl:template name="min">
		<xsl:param name="nodes" select="/.."/>
		<xsl:param name="defaultValue">0</xsl:param>
		<xsl:call-template name="minMax">
			<xsl:with-param name="nodes" select="$nodes"/>
			<xsl:with-param name="defaultValue" select="$defaultValue"/>
			<xsl:with-param name="minOrMax">min</xsl:with-param>
		</xsl:call-template>
	</xsl:template>
	<!--
	
	Max template. Returns maximum numeric value from $nodes. If no numeric nodes or no nodes then it
	returns $defaultValue
	-->
	<xsl:template name="max">
		<xsl:param name="nodes" select="/.."/>
		<xsl:param name="defaultValue">0</xsl:param>
		<xsl:call-template name="minMax">
			<xsl:with-param name="nodes" select="$nodes"/>
			<xsl:with-param name="defaultValue" select="$defaultValue"/>
			<xsl:with-param name="minOrMax">max</xsl:with-param>
		</xsl:call-template>
	</xsl:template>
	<!--
	
	Don't use directly - use 'min' or 'max' templates
	
	Returns min or max numeric value of $nodes.  If no numeric nodes or no nodes then it
	returns $defaultValue

	-->
	<xsl:template name="minMax">
		<xsl:param name="nodes" select="/.."/>
		<xsl:param name="minOrMax">max</xsl:param>
		<xsl:param name="defaultValue"/>
		<!--
		
		-->
		<xsl:choose>
			<xsl:when test="not($nodes[number() = number()])">
				<xsl:value-of select="$defaultValue"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:choose>
					<xsl:when test="translate($minOrMax,'minax','MINAX') = 'MAX'">
						<xsl:for-each select="$nodes[number() = number()]">
							<xsl:sort data-type="number" order="descending"/>
							<xsl:if test="position() = 1">
								<xsl:value-of select="number(.)"/>
							</xsl:if>
						</xsl:for-each>
					</xsl:when>
					<xsl:otherwise>
						<xsl:for-each select="$nodes[number() = number()]">
							<xsl:sort data-type="number" order="ascending"/>
							<xsl:if test="position() = 1">
								<xsl:value-of select="number(.)"/>
							</xsl:if>
						</xsl:for-each>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	
	
</xsl:stylesheet>




 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread