0

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.

Community
  • 1
  • 1
BlackLight
  • 122
  • 1
  • 8
  • 2
    The FF message most probably means *infinite recursion* and this means that there was (real) stack overflow. You need to correct your code. Either provide your code (edit the question and enter the code), or ask for a working XSLT 1.0 string replacement solution (there are plenty of such in various answers in the xslt tag). – Dimitre Novatchev May 30 '11 at 01:10
  • 1
    You can also try to use Saxon CE, which is an XSLT 2.0 implementation operating client-side as part of the browser. – Dimitre Novatchev May 30 '11 at 01:13
  • I add with regret: when will the major browser projects move to the superior XSLT 2.0? This whole Q would be negated.. – Paulb Sep 04 '14 at 22:27

1 Answers1

2

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.

jasso
  • 13,736
  • 2
  • 36
  • 50
  • 1
    Thanks, it did the trick. I didn't know that XSLT made this difference between strings and node names, good to know :) – BlackLight May 30 '11 at 11:46