Subject: Re: Best way to handle multiple string replacements? From: Jeni Tennison <Jeni.Tennison@xxxxxxxxxxxxxxxx> Date: Tue, 06 Jun 2000 12:59:51 +0100 |
Warren, >Does anyone have any cool templates that take a hashtable of >find and replace strings that are all applied to one piece of >input text? Here is *a* way to do it. I'm not sure that it's the most efficient, but it's the principal that counts, and the principal is to XMLise the information about what you want to find and replace, or the characters that need to be escaped. So, make up a namespace for this information and include it in your file. For the replacements that you're using, I created two sets of elements: <foo:special_characters> <foo:char>_</foo:char> <foo:char>%</foo:char> <foo:char>$</foo:char> <foo:char>{</foo:char> <foo:char>}</foo:char> <foo:char>&</foo:char> </foo:special_characters> <foo:string_replacement> <foo:search> <foo:find>±</foo:find> <foo:replace>$\pm$</foo:replace> </foo:search> <foo:search> <foo:find>°</foo:find> <foo:replace>$\degree$</foo:replace> </foo:search> <foo:search> <foo:find>©</foo:find> <foo:replace>\copyright</foo:replace> </foo:search> <foo:search> <foo:find>¶</foo:find> <foo:replace>$\mathbb{P}$</foo:replace> </foo:search> </foo:string_replacement> This separates out the data about the replacements that you want to make (the what). Now you want to specify the procedure about how to do those replacements (the how). I've called your existing templates to actually do the replacement, and focussed on identifying what you want to exchange. First, then, the 'escape_special_characters' template. Basically, you want to first replace the characters on the $input_text, then replace the strings on the output from that: <xsl:template name="replace_special_characters"> <xsl:with-param name="input_text" /> <xsl:variable name="replaced_text"> <xsl:call-template name="replace_characters"> <xsl:with-param name="input_text" select="$input_text" /> </xsl:call-template> </xsl:variable> <xsl:call-template name="replace_strings"> <xsl:with-param name="input_text" select="$replaced_text" /> </xsl:call-template> </xsl:template> The two templates for replacing the characters and replacing the strings are much the same, so I'll only go through the one replacing the characters in detail. <xsl:template name="replace_characters"> ... </xsl:template> First, we need to declare a couple of parameters that we're going to use. One is the text that we need to replace and the other is one to keep track of where we are in the set of replacements that we need to make. I've done this second using an index number, defaulting it to 1 as the initial value. <xsl:with-param name="input_text" /> <xsl:with-param name="char">1</xsl:with-param> Then we need to create the new string, with the replacements made. We do this by calling your put_slash_in_front_of template, with the $input_text that we already have and the $special_char that is identified by the index number. We get at the character by getting the nth foo:char within the current document (the stylesheet), i.e. document('')//foo:char[$char]. <xsl:variable name="replaced_text"> <xsl:call-template name="put_slash_in_front_of"> <xsl:with-param name="input_text" select="$input_text" /> <xsl:with-param name="special_char" select="document('')//foo:char[$char]" /> </xsl:call-template> </xsl:variable> Now the recursive part. If we haven't got to the end of the list of characters that need to be escaped, then we have to move on to the next one, calling this same template with the next index, and with the text that we've created (i.e. that's already been escaped). If we've run out of foo:char, then we just return the escaped text. <xsl:choose> <xsl:when test="$char < count(document('')//foo:char)"> <xsl:call-template name="replace_characters"> <xsl:with-param name="input_text" select="$replaced_text" /> <xsl:with-param name="char" select="$char + 1" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$replaced_text" /> </xsl:otherwise> </xsl:choose> And that's it. The other one in full is: <xsl:template name="replace_strings"> <xsl:param name="input_text" /> <xsl:param name="search">1</xsl:param> <xsl:variable name="replaced_text"> <xsl:call-template name="latex_string_replace"> <xsl:with-param name="input_text" select="$input_text" /> <xsl:with-param name="find" select="document('')//foo:search[$search]/foo:find" /> <xsl:with-param name="replace" select="document('')//foo:search[$search]/foo:replace" /> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$search < count(document('')//foo:search)"> <xsl:call-template name="replace_strings"> <xsl:with-param name="input_text" select="$replaced_text" /> <xsl:with-param name="search" select="$search + 1" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$replaced_text" /> </xsl:otherwise> </xsl:choose> </xsl:template> This is tested in SAXON and gives the same results as your original approach, but it is much easier to extend. You could probably apply templates to the foo:char and foo:search nodes as an alternative approach - the important thing is to separate out the what from the how, not the how you do the how :) I hope that helps, Jeni Dr Jeni Tennison Epistemics Ltd, Strelley Hall, Nottingham, NG8 6PE Telephone 0115 9061301 ? Fax 0115 9061304 ? Email jeni.tennison@xxxxxxxxxxxxxxxx XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: Best way to handle multiple str, David Carlisle | Thread | Re: Best way to handle multiple str, Sebastian Rahtz |
Re: XSL Performance, Lars Marius Garshol | Date | Re: FW: XSLT applet recommendation , Nick Browne |
Month |