Search code examples
xmlxsltreplacexslt-2.0

XSLT replace function in Firefox


I'm trying to perform a string replace through XSLT, but I actually see no way for that in Firefox.

When I use the XSLT 2.0 replace() function through something like this:

<xsl:value-of select="replace(., 'old', 'new')"/>

I get in Firefox the error "An unknown XPath extension function was called". When I try to use any XSLT 1.0 compatible template that performs the replacement I get the error "XSLT Stylesheet (possibly) contains a recursion" (of course it contains a recursion, I see no other way for performing a string replacement in XSLT without a recursive function).

So, no chance to use the XSLT 2.0 replace() function, and no chance to use a recursive template. How do I perform the trick using XSLT? Please no suggestions to make it on the server side, I implemented my whole website in order to operate client-side only transformations and I can't roll back just because of one issue, and it's not right that in 2011 I can't use a powerful technology like XSLT because of its buggy and incomplete implementations.

EDIT:

The code I used is the same provided here: XSLT Replace function not found

I used this XML for testing:

<?xml version="1.0"?>
<?xml-stylesheet href="/example.xsl" type="text/xsl"?>

<content>lol</content>

and this XSLT:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>

<xsl:template name="string-replace-all">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:choose>
<xsl:when test="contains($text,$replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$by"/>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="content">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="lolasd"/>
<xsl:with-param name="replace" select="lol"/>
<xsl:with-param name="by" select="asd"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>

On Firefox I get "XSLT Stylesheet (possibly) contains a recursion". Well, of course it does, otherwise it wouldn't be a string replacement template. Other templates picked up around the net using the same style trigger the same issue as well.


Solution

  • With this document

    <content>lol</content>
    

    these parameters

    <xsl:with-param name="text" select="lolasd"/>
    <xsl:with-param name="replace" select="lol"/>
    <xsl:with-param name="by" select="asd"/>
    

    will be empty, and therefore this condition

    <xsl:when test="contains($text,$replace)">
    

    will always be true, and your code will recurse ad infinitum.

    I guess your intention was to select a string instead a node in your <xsl:with-param> elements but you forgot to use quotes/apostrophes. What you should have is something like

    <xsl:with-param name="replace" select="'lol'"/>
    

    Nevertheless, you should add a check for a case, where parameters are empty to avoid such problem, if you end up selecting emtpy strings.