This post contains attachments v20011221171005.zip 
Summary
This snippet is an extension of Trace Wilson's snippet "How to do a search and replace in XSLT" posted 23 Feb 2001. It shows how to repeteadly find and replace all occurences of any number of different strings in a text node.
Trace Wilson's example demonstrates how to find and replace all occurences of a single string with another string in a text node. This inevitably raises the question of processsing the same text repeteadly for different strings. This snippet shows how to do this. One can also view it as generalization of XPath function translate, that makes it possible to replace all occurences of any number of different characters with other characters. This code makes it possible to do with substrings what translate does with characters.
The main part of the Trace's snippet is a recursive template (named replace-text) taking 3 parameters: text (text node to be processed), replace (string to be replaced) and by (replacing string). This snippet is, like the Trace's one, based on a recursive template (named multi-replace), which however, instead of a text node, scans a specially formatted control string (represented by replace-by parameter), containing pairs of replaced-to-be and replacing substrings. After extracting each pair it calls Trace's template with appropriate parameters and stores the result in the translated variable. If there are more string pairs in the control string, the template calls itself recursively with translated variable passed as text parameter, and the remaining part of control string passed as replace-by parameter. The format of the control string is this: each string to be replaced should be ended with [:] and each replacing string with {|}. The control string should not contain any other characters, e.g. spaces or linefeeds (unless they are part of replacing or replaced-to-be strings). For instance to replace all occurences of Jim with James and all occurences of Bill with William one should use the following control string: 'Jim[:]James{|}Bill[:]William{|}' Since in this application the result tree fragment generated by the Trace's template is usually processed further, I have had to change slightly his template by removing the disable-output-escaping=yes attribute from the xsl:value-of element. Otherwise it would be not fully conforming with the XSLT specification, and some processors (e.g. XT) would report error. Besides, in this application that attribute is no longer necessary, as its function has been taken over by the same attribute in my multi-replace template.
As an example consider following xml: <text> Jim went to school. γ = α + β </text> This text contains three greek characters coded as numerical entities, as well as fixed spaces coded also as numerical entities ( ). Suppose we want to convert this xml to html with greek characters coded as entities α β and γ, and the fixed spaces coded as . In addition we want to replace Jim with James and supplement the linefeeds with <br>. To achieve this it is only necessary to call the multi-replace template with the following control string (replace-by parameter):
'Jim[:]James{|} [:]<br> {|} [:]&nbsp;{|}α[:]&alpha;{|}β[:]&beta;{|}γ[:]&gamma;{|}'.
(Of course the < > & characters had to be escaped).
This should give, as a result, the following html:
<html> <body><br> James went to school.<br> γ = α + β<br> </body> </html>
|