I also wrote a solution using recursion before, but the only thing that bothered me was performance, and if there would be some memory or some stackoverflow because of this. I was wondering if there would be any solution using <xsl: value-of> or <copy-of>? Also, please let me know if there are any improvements in the solution below if recursion can be converted to a loop, etc.
<xsl:template match="text()" mode="literalHTML">
<xsl:variable name="txt" select="."/>
<xsl:value-of select="smc:escapeChar(smc:escapeChar(smc:escapeChar($txt,'&','&amp;'),'<','&lt;'),'>','&gt;')"/>
</xsl:template>
<xsl:function name="smc:escapeChar">
<xsl:param name="txt"/>
<xsl:param name="char"/>
<xsl:param name="subs"/>
<xsl:result>
<xsl:variable name="result">
<xsl:choose>
<xsl:when test="contains($txt, $char)">
<xsl:variable name="after" select="substring-after($txt,$char)"/>
<xsl:value-of select="substring-before($txt,$char)"/>
<xsl:value-of select="$subs"/>
<xsl:value-of select="smc:escapeChar($after,$char,$subs)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$txt"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$result"></xsl:value-of>
</xsl:result>
</xsl:function>
source
share