This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
replace-string() convenience function proposal
- To: <xsl-list at mulberrytech dot com>
- Subject: replace-string() convenience function proposal
- From: "Evan Lenz" <elenz at xyzfind dot com>
- Date: Wed, 30 Aug 2000 12:54:41 -0700
- Reply-To: xsl-list at mulberrytech dot com
I would like a function such as replace-string() that would allow me to
replace one specified string with another specified string, within a
specified string. For example, replace-string("Hello there", "Hello", "Hi")
would return "Hi there". I use the following stylesheet (adapted from an
example in Kay's book) to do this for me now.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="replace-string">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="with"/>
<xsl:choose>
<xsl:when test="contains($text,$replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$with"/>
<xsl:call-template name="replace-string">
<xsl:with-param name="text"
select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="with" select="$with"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Not only is the implementation lengthy and messy, but each time you call it,
you have to pass parameters all over the place. Here's an example of where
I need to escape curly braces in attribute values in a generated stylesheet
(admittedly not the most frequent use-case, but a simple requirement
nevertheless):
<!-- brace-escaping to guard against interpretation as AVTs in the
output -->
<xsl:template match="@*" mode="rootRule">
<xsl:variable name="leftBraceReplaced">
<xsl:call-template name="replace-string"> <!-- imported template -->
<xsl:with-param name="text" select="."/>
<xsl:with-param name="replace" select="'{'"/>
<xsl:with-param name="with" select="'{{'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="bothBracesReplaced">
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$leftBraceReplaced"/>
<xsl:with-param name="replace" select="'}'"/>
<xsl:with-param name="with" select="'}}'"/>
</xsl:call-template>
</xsl:variable>
<xsl:attribute name="{name()}">
<xsl:value-of select="$bothBracesReplaced"/>
</xsl:attribute>
</xsl:template>
Now, compare all of that code to the following code:
<xsl:attribute name="{name()}">
<xsl:value-of select="replace-string(replace-string(., '{', '{{'), '}',
'}}')"/>
</xsl:attribute>
The translate() function is great for one-to-one character replacements, but
as soon as you want to replace a character with, say, two characters (as in
my example), you have to write a named template that recursively calls
itself, and pass all the parameters via <xsl:with-param/> each time you need
to call it, which, as you can see, can get quite ugly.
I don't care what this function is called; maybe just replace() would be
better.
Anyone want to second this motion (assuming it hasn't already been
proposed)?
Evan Lenz
elenz@xyzfind.com
http://www.xyzfind.com
XYZFind Corp. "Building Better Search"
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list