Improving the performance of XSL
- by Rachel
In the below XSL for the variable "insert-data", I have an input param with the structure,
<insert-data>
<data compareIndex="4" nodeName="d1e1">
<a/>
</data>
<data compareIndex="5" nodeName="d1e1">
<b/>
</data>
<data compareIndex="7" nodeName="d1e2">
<a/>
</data>
<data compareIndex="9" nodeName="d1e2">
<b/>
</data>
</insert-data>
where "nodeName" is the id of a node and "compareIndex" is the position of the text content relative to the node having id "$nodeName".
I am using the below XSL to select all the text nodes(generate-id) that satisfy the above condition and construct a data xml. The below implementation works perfectly but the time taken for the execution is in min. Is there a better way of implementing or is there any in-efficient operation being used. From my observation the code where the preceding text length is calculated consumes the major time. Please share your thoughts to improve the performance of the XSL. I am using Java SAXON XSL transformer.
<xsl:variable name="insert-data" as="element()*">
<xsl:for-each select="$insert-file/insert-data/data">
<xsl:sort select="xsd:integer(@index)"/>
<xsl:variable name="compareIndex" select="xsd:integer(@compareIndex)" />
<xsl:variable name="nodeName" select="@nodeName" />
<xsl:variable name="nodeContent" as="node()">
<xsl:copy-of select="node()"/>
</xsl:variable>
<xsl:for-each select="$main-root/*//text()[ancestor::*[@id = $nodeName]]">
<xsl:variable name="preTextLength" as="xsd:integer" select="sum((preceding::text())[. ancestor::*[@id = $nodeName]]/string-length(.))" />
<xsl:variable name="currentTextLength" as="xsd:integer" select="string-length(.)" />
<xsl:variable name="sum" select="$preTextLength + $currentTextLength" as="xsd:integer"></xsl:variable>
<xsl:variable name="split-index" select="$compareIndex - $preTextLength" as="xsd:integer"></xsl:variable>
<xsl:if test="($sum ge $compareIndex) and ($compareIndex gt $preTextLength)">
<data split-index="{$split-index}" text-id="{generate-id(.)}">
<xsl:copy-of select="$nodeContent"/>
</data>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>