Jim,
I remember doing something similar with XSLT 1.0, and it should work fine
under 2.0 too. I created a new mode and passed the string to perform the
multiple replace as a parameter; then applied templates changing the context
to the "database" of find/replace characters. The template for that new
mode performed the replace for that "record", then applied templates on the
following sibling passing the new string along... Something like this:
Say you use the following variable for the various characters:
<xsl:variable name="ReplaceDb">
<ReplaceTable>
<replacements>
<replace><<</replace>
<with>“</with>
</replacements>
<replacements>
<replace>>></replace>
<with>”</with>
</replacements>
etc
</xsl:variable>
Then if the string to perform the multiple replacements on is $String, I
used something like this:
<xsl:apply-templates select="$ReplaceDb/*/*[1]" mode="DbStringReplace">
<xsl:with-param name="InputString" select=" $String "/>
<xsl:with-param name="SearchCharacterName" select=" 'replace'
"/>
<xsl:with-param name="ReplaceCharacterName" select=" 'with' "/>
</xsl:apply-templates>
The XSLT 1.0 template rule I had hanging around for the "DbSringReplace"
mode is pasted below. Note that it also calls a "StringSubstitute"
template, but you can just use the replace() function for that... Also note
I haven't used or testing this thing in a while :-)
Hope that helps!
Cheers,
...sam
<xsl:template match="*" mode="DbStringReplace">
<xsl:param name="InputString"/>
<xsl:param name="SearchCharacterName"/>
<xsl:param name="ReplaceCharacterName"/>
<xsl:choose>
<!-- first confirm strings aren't empty -->
<xsl:when test="$InputString = '' or
$SearchCharacterName = '' or $ReplaceCharacterName = ''">
<xsl:message>ERROR!!!</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="SearchString"
select="*[local-name()=$SearchCharacterName]"/>
<xsl:variable name="ReplaceString"
select="*[local-name()=$ReplaceCharacterName]"/>
<xsl:variable name="UpdatedInputString">
<xsl:choose>
<xsl:when
test="not(contains($InputString[1], $SearchString))">
<xsl:value-of
select="$InputString"/>
</xsl:when>
<xsl:otherwise>
<!-- output string before SearchString, then output ReplaceString, then
check is more in remaining part of InputString -->
<xsl:value-of
select="concat(substring-before($InputString,$SearchString),$ReplaceString)"/>
<xsl:variable
name="RemString" select="substring-after($InputString,$SearchString)"/>
<xsl:choose>
<xsl:when test="contains($RemString, $SearchString)">
<!-- if so, call recursively to finish replacing -->
<xsl:call-template name="StringSubstitute">
<xsl:with-param name="InputString"
select="$RemString"/>
<xsl:with-param name="SearchString"
select="$SearchString"/>
<xsl:with-param name="ReplaceString"
select="$ReplaceString"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise> <!-- output remainder of the string -->
<xsl:value-of
select="substring-after($InputString,$SearchString)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when
test="following-sibling::*"> <!-- now process the next in line -->
<xsl:apply-templates
select="following-sibling::*[1]" mode="DbStringReplace">
<xsl:with-param
name="InputString" select="$UpdatedInputString"/>
<xsl:with-param
name="SearchCharacterName" select="$SearchCharacterName"/>
<xsl:with-param
name="ReplaceCharacterName" select="$ReplaceCharacterName"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise><xsl:value-of
select="$UpdatedInputString"/></xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>