Hi David,
I notice that most XSLT 1.0 solutions use recursive templates and
wondered if there is any benefit in a solution that re-applies
templates to text nodes many times, rather than explicitly calling a
recursive template. For moderately big files it seems to perform
quite well, though I haven't tested it too much, so there may be
hidden problems. I guess this approach is essentially the same as
recursion, but you don't have to figure out which matched string
comes first (though you do need node-set).
What you're doing in your stylesheet, as far as I can tell, is
creating new text nodes for the substrings before and after the
matched string. In general, it's a bad idea to create new nodes if you
can get away with using a string or number instead because nodes take
up a lot more memory than simple values. Also, all you've done really
is add a level of indirection -- rather than call the template
recursively directly, you're calling it recursively via a template
that matches the new text node that you've generated -- which might
add a little to the time (it certainly won't make it quicker).
So I'm afraid that I can't see much benefit in the approach you're
suggesting. It should be more efficient to use:
<xsl:template match="text()" priority="2"><!-- need priority to overcome the
node match below -->
<xsl:call-template name="markup">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template name="markup">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, 'document')">
<xsl:call-template name="markup">
<xsl:with-param name="text"
select="substring-before($text, 'document')" />
</xsl:call-template>
<special>document</special>
<xsl:call-template name="markup">
<xsl:with-param name="text"
select="substring-after($text, 'document')" />
</xsl:call-template>
<xsl:when test="contains($text, 'markup')">
<xsl:call-template name="markup">
<xsl:with-param name="text"
select="substring-before($text, 'markup')" />
</xsl:call-template>
<special>markup</special>
<xsl:call-template name="markup">
<xsl:with-param name="text"
select="substring-after($text, 'markup')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$text"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
But of course you should test it to see if my assumptions are correct.
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list