Re: [xsl] Using XSLT to add markup to a document

Subject: Re: [xsl] Using XSLT to add markup to a document
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 7 Jul 2003 16:51:32 +0100
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


Current Thread