[xsl] search and replace multiple characters fails

Subject: [xsl] search and replace multiple characters fails
From: Greg Martel <gregm@xxxxxxxxxxx>
Date: Fri, 19 Oct 2001 06:42:02 -0500
I have been working with XSLT 6 weeks. I am having trouble with searching and replacing for multiple characters (one character is no problem).


<xsl:template name="SANDR"> <xsl:param name="string"/> <xsl:param name="newchar1"/> <xsl:param name="newchar2"/> <xsl:param name="newchar3"/> <xsl:param name="newchar4"/> <xsl:param name="newchar5"/> <xsl:choose> <xsl:when test="contains($string, '&#8217;')"> <xsl:value-of select="substring-before($string, '&#8217;')"/> <xsl:value-of select="$newchar1"/> <xsl:call-template name="SANDR"> <xsl:with-param name="string" select="substring-after($string, '&#8217;')"/> <xsl:with-param name="newchar1" select="$newchar1"/> </xsl:call-template> </xsl:when>

<xsl:when test="contains($string, '&#8226;')">
	<xsl:value-of select="substring-before($string, '&#8226;')" />
	<xsl:value-of select="$newchar2"/>
	<xsl:call-template name="SANDR">
		<xsl:with-param name="string"
               select="substring-after($string, '&#8226;')"/>
	<xsl:with-param name="newchar2" select="$newchar2"/>
	</xsl:call-template>
</xsl:when>

<xsl:when test="contains($string, '&#9642;')">
	<xsl:value-of select="substring-before($string, '&#9642;')"/>
		<xsl:value-of select="$newchar3"/>
		<xsl:call-template name="SANDR">
		<xsl:with-param name="string"
               select="substring-after($string, '&#9642;')"/>
		<xsl:with-param name="newchar3" select="$newchar3"/>
	</xsl:call-template>
 </xsl:when>

<xsl:when test="contains($string, '@')">
	<xsl:value-of select="substring-before($string, '@')"/>
		<xsl:value-of select="$newchar4"/>
		<xsl:call-template name="SANDR">
		<xsl:with-param name="string"
               select="substring-after($string, '@')"/>
		<xsl:with-param name="newchar4" select="$newchar4"/>
	</xsl:call-template>
</xsl:when>

<xsl:when test="contains($string, '&#8211;')">
	<xsl:value-of select="substring-before($string, '&#8211;')"/>
	<xsl:value-of select="$newchar5"/>
		<xsl:call-template name="SANDR">
		<xsl:with-param name="string"
               select="substring-after($string, '&#8211;')"/>
		<xsl:with-param name="newchar5" select="$newchar5"/>
	</xsl:call-template>
</xsl:when>

<xsl:otherwise><xsl:value-of select="$string" /></xsl:otherwise>
</xsl:choose>
</xsl:template>

Obviously, this template has at least one problem: If a TextString has more than one of these characters, only the 1st one found gets replaced. (When one of the conditions is met for a given context node, the processor stops looking at the other ones, thus making it unable to find & replace more than one character in this manner). I came up with a solution that SHOULD work but doesn't. Basically, rather than having one template with 5 conditions, i chose to have 5 different templates each with one condition; but i have some rather unexpected results.


<xsl:template name="SANDR"> <xsl:call-template name="CHARFIX1"> <xsl:with-param name="string" select="."/> <xsl:with-param name="newchar1" select="'&lt;\#39&gt;'"/> </xsl:call-template>

	<xsl:call-template name="CHARFIX2">
		<xsl:with-param name="string" select="."/>
		<xsl:with-param name="newchar2" select="'&lt;\#165&gt;'"/>
	</xsl:call-template>

	&etc, for CHARFIX3, CHARFIX4, CHARFIX5
	</xsl:call-template>
</xsl:template>


<xsl:template name="CHARFIX1"> <xsl:param name="string"/> <xsl:param name="newchar1"/> <xsl:if test="contains($string, '&#8217;')"> <xsl:value-of select="substring-before($string, '&#8217;')"/> <xsl:value-of select="$newchar1"/> <xsl:value-of select="substring-after($string, '&#8217;')"/></xsl:if> </xsl:template>


&etc, for CHARFIX2, CHARFIX3, and CHARFIX4 until 5 which goes:



<xsl:template name="CHARFIX5"> <xsl:param name="string"/> <xsl:param name="newchar5"/> <xsl:choose> <xsl:when test="contains($string, '&#8211;')"> <xsl:value-of select="substring-before($string, '&#8211;')"/> <xsl:value-of select="$newchar5"/> <xsl:value-of select="substring-after($string, '&#8211;')"/> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="contains($string, '&#8217;')"></xsl:when> <xsl:when test="contains($string, '&#8226;')"></xsl:when> <xsl:when test="contains($string, '&#9642;')"></xsl:when> <xsl:when test="contains($string, '@')"></xsl:when> <xsl:otherwise><xsl:value-of select="$string"/></xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template>



With this S and R routine, I get only the FIRST occurrence of any character in the list. So where before i got:

<\#165> Text. Text Text. <\#165> Text Text. <\#165> Text

now i get: <\#165> Text. Text Text. ? Text Text. ? Text

(where <\#165> is a successful replacement and ? is not)


I don't understand why this is happening. Can anyone see what is wrong here? ANd if there is a problem inherent for search and replace for multiple characters--how do other folks deal with it?



-- Thanks Muchos,

Greg Martel


-- Thanks Muchos,

Greg Martel
Coordinator of Enchiladas

XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list


Current Thread