XSLT 1.0 doesn't have robust text search-and-replace. You can gin something up that uses contains
, substring-before
, and substring-after
, but you have to use a recursive template to handle the case where the string you're trying to fix has multiple occurrences of the substring.
This works, assuming that your transform that moves and renames elements is a variant of the identity transform:
<xsl:template match="text()">
<xsl:call-template name="replace">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, 'bar')">
<xsl:call-template name="replace">
<xsl:with-param name="text" select="concat(
substring-before($text, 'bar'),
'myBar',
substring-after($text, 'bar'))"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Note that anywhere you're copying the value of an element using value-of
, you need to be using apply-templates
; change this:
<xsl:template match="someElement">
<renamedElement>
<xsl:value-of select="."/>
<renamedElement>
</xsl:template>
into this:
<xsl:template match="someElement">
<renamedElement>
<xsl:apply-templates select="text()"/>
<renamedElement>
</xsl:template>
Doing multiple replacements is a bit trickier. You have to extend the replace
template to take a searchFor
and replaceWith
arguments, which is easy enough, and then do this in the text()
template:
<xsl:variable name="pass1">
<xsl:call-template name="replace">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="searchFor">bar</xsl:with-param>
<xsl:with-param name="replaceWith">myBar</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="pass2">
<xsl:call-template name="replace">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="searchFor">bar</xsl:with-param>
<xsl:with-param name="replaceWith">myBar</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$pass2"/>
In XSLT 2.0, which supports using regular expressions on text nodes, this is a lot easier. You still create a template that matches text()
, but it just has a call to replace
. See this article for plenty of information, if you're fortunate enough to be able to use XSLT 2.0.