Rectangle 27 2

Why don't you just use the standard XSLT 2.0 replace function? Or the XSLT 1.0 replace implementation xslt 1.0 string replace function

Hm.. @_FailedDev, The link you provide is for replacing single characters with single characters. This cannot be used in the current problem, where it is necessary to replace one character (') with two characters (\').

@DimitreNovatchev somehow magically the link copied from the available answer we wrong. Thanks for pointing this out.

php - XSLT: Replace single quotes by \' - Stack Overflow

php xslt
Rectangle 27 2

Why don't you just use the standard XSLT 2.0 replace function? Or the XSLT 1.0 replace implementation xslt 1.0 string replace function

Hm.. @_FailedDev, The link you provide is for replacing single characters with single characters. This cannot be used in the current problem, where it is necessary to replace one character (') with two characters (\').

@DimitreNovatchev somehow magically the link copied from the available answer we wrong. Thanks for pointing this out.

php - XSLT: Replace single quotes by \' - Stack Overflow

php xslt
Rectangle 27 65

A very simple solution (that will work as long as your string value doesn't have spaces):

translate(normalize-space(translate('aa::bb::cc',':',' ')),' ',',')
  • normalize-space() to collapse multiple whitespace characters into a single space " "

A more robust solution would be to use a recursive template:

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

You can use it like this:

<xsl:call-template name="replace-string">
  <xsl:with-param name="text" select="'aa::bb::cc'"/>
  <xsl:with-param name="replace" select="'::'" />
  <xsl:with-param name="with" select="','"/>
</xsl:call-template>

+1 for a good answer.

xslt 1.0 string replace function - Stack Overflow

xslt xslt-1.0
Rectangle 27 65

A very simple solution (that will work as long as your string value doesn't have spaces):

translate(normalize-space(translate('aa::bb::cc',':',' ')),' ',',')
  • normalize-space() to collapse multiple whitespace characters into a single space " "

A more robust solution would be to use a recursive template:

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

You can use it like this:

<xsl:call-template name="replace-string">
  <xsl:with-param name="text" select="'aa::bb::cc'"/>
  <xsl:with-param name="replace" select="'::'" />
  <xsl:with-param name="with" select="','"/>
</xsl:call-template>

xslt 1.0 string replace function - Stack Overflow

xslt xslt-1.0
Rectangle 27 116

replace

Codesling has a template for string-replace you can use as a substitute for the function:

<xsl:template name="string-replace-all">
    <xsl:param name="text" />
    <xsl:param name="replace" />
    <xsl:param name="by" />
    <xsl:choose>
        <xsl:when test="$text = '' or $replace = ''or not($replace)" >
            <!-- Prevent this routine from hanging -->
            <xsl:value-of select="$text" />
        </xsl:when>
        <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:variable name="newtext">
    <xsl:call-template name="string-replace-all">
        <xsl:with-param name="text" select="$text" />
        <xsl:with-param name="replace" select="a" />
        <xsl:with-param name="by" select="b" />
    </xsl:call-template>
</xsl:variable>

On the other hand, if you literally only need to replace one character with another, you can call translate which has a similar signature. Something like this should work fine:

<xsl:variable name="newtext" select="translate($text,'a','b')"/>

Also, note, in this example, I changed the variable name to "newtext", in XSLT variables are immutable, so you can't do the equivalent of $foo = $foo like you had in your original code.

Thanks Mark, but now I am getting this error: An unknown XPath extension function was called

@aximili, sorry, got XSLT 1.0 and 2.0 confused, edited...should be good to go now.

This answer is wrong! The replace function in XSLT replaces corresponding SINGLE CHARACTERS, not the whole strings! See for example here: w3schools.com/xpath/xpath_functions.asp

@Jakub You're thinking of translate, not replace. The replace function in XPath 2.0 treats its second argument as a regular expression and replaces all matches of that expression with the specified replacement string (which may include $n references to capturing groups in the regex). The translate function (in 1.0 and 2.0) is the one that does single-character-for-single-character replacements.

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

xpath - XSLT string replace - Stack Overflow

xslt xpath replace xslt-1.0 xpath-1.0
Rectangle 27 116

replace

Codesling has a template for string-replace you can use as a substitute for the function:

<xsl:template name="string-replace-all">
    <xsl:param name="text" />
    <xsl:param name="replace" />
    <xsl:param name="by" />
    <xsl:choose>
        <xsl:when test="$text = '' or $replace = ''or not($replace)" >
            <!-- Prevent this routine from hanging -->
            <xsl:value-of select="$text" />
        </xsl:when>
        <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:variable name="newtext">
    <xsl:call-template name="string-replace-all">
        <xsl:with-param name="text" select="$text" />
        <xsl:with-param name="replace" select="a" />
        <xsl:with-param name="by" select="b" />
    </xsl:call-template>
</xsl:variable>

On the other hand, if you literally only need to replace one character with another, you can call translate which has a similar signature. Something like this should work fine:

<xsl:variable name="newtext" select="translate($text,'a','b')"/>

Also, note, in this example, I changed the variable name to "newtext", in XSLT variables are immutable, so you can't do the equivalent of $foo = $foo like you had in your original code.

Thanks Mark, but now I am getting this error: An unknown XPath extension function was called

@aximili, sorry, got XSLT 1.0 and 2.0 confused, edited...should be good to go now.

This answer is wrong! The replace function in XSLT replaces corresponding SINGLE CHARACTERS, not the whole strings! See for example here: w3schools.com/xpath/xpath_functions.asp

@Jakub You're thinking of translate, not replace. The replace function in XPath 2.0 treats its second argument as a regular expression and replaces all matches of that expression with the specified replacement string (which may include $n references to capturing groups in the regex). The translate function (in 1.0 and 2.0) is the one that does single-character-for-single-character replacements.

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

xpath - XSLT string replace - Stack Overflow

xslt xpath replace xslt-1.0 xpath-1.0
Rectangle 27 29

Here is the XSLT function which will work similar to the String.Replace() function of C#.

This template has the 3 Parameters as below

text

replace :- the string which you want to replace

by :- the string which will reply by new string

<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:variable name="myVariable ">
  <xsl:call-template name="string-replace-all">
    <xsl:with-param name="text" select="'This is a {old} text'" />
    <xsl:with-param name="replace" select="'{old}'" />
    <xsl:with-param name="by" select="'New'" />
  </xsl:call-template>
</xsl:variable>

You can also refer the below URL for the details.

xpath - XSLT string replace - Stack Overflow

xslt xpath replace xslt-1.0 xpath-1.0
Rectangle 27 29

Here is the XSLT function which will work similar to the String.Replace() function of C#.

This template has the 3 Parameters as below

text

replace :- the string which you want to replace

by :- the string which will reply by new string

<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:variable name="myVariable ">
  <xsl:call-template name="string-replace-all">
    <xsl:with-param name="text" select="'This is a {old} text'" />
    <xsl:with-param name="replace" select="'{old}'" />
    <xsl:with-param name="by" select="'New'" />
  </xsl:call-template>
</xsl:variable>

You can also refer the below URL for the details.

xpath - XSLT string replace - Stack Overflow

xslt xpath replace xslt-1.0 xpath-1.0
Rectangle 27 4

For simple string replacement the translate function (available in xslt 1.0) worked fine for me.

The translate function only works on single characters.

xml - XSLT Replace function not found - Stack Overflow

xml regex xslt xpath replace
Rectangle 27 4

For simple string replacement the translate function (available in xslt 1.0) worked fine for me.

The translate function only works on single characters.

xml - XSLT Replace function not found - Stack Overflow

xml regex xslt xpath replace
Rectangle 27 30

The replace function is only available in XSLT version 2.0, not in version 1.0 which is what Visual Studio uses. Just because you've specified version="2.0" doesn't mean that Visual Studio supports it.

(Taken from the link above)

<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:otherwise>
  <td style="border: solid 1px black; background-color:#00CC66;">
    <xsl:variable name="FeatureInfo" select="Text" />
    <xsl:call-template name="string-replace-all">
      <xsl:with-param name="text" select="$FeatureInfo"/>
      <xsl:with-param name="replace" select="Feature="/>
      <xsl:with-param name="by" select="TESTING"/>
    </xsl:call-template>
  </td>
</xsl:otherwise>

You need single quotes in your <xsl:with-param>s, such as select="'TESTING'".

xml - XSLT Replace function not found - Stack Overflow

xml regex xslt xpath replace
Rectangle 27 30

The replace function is only available in XSLT version 2.0, not in version 1.0 which is what Visual Studio uses. Just because you've specified version="2.0" doesn't mean that Visual Studio supports it.

(Taken from the link above)

<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:otherwise>
  <td style="border: solid 1px black; background-color:#00CC66;">
    <xsl:variable name="FeatureInfo" select="Text" />
    <xsl:call-template name="string-replace-all">
      <xsl:with-param name="text" select="$FeatureInfo"/>
      <xsl:with-param name="replace" select="Feature="/>
      <xsl:with-param name="by" select="TESTING"/>
    </xsl:call-template>
  </td>
</xsl:otherwise>

You need single quotes in your <xsl:with-param>s, such as select="'TESTING'".

xml - XSLT Replace function not found - Stack Overflow

xml regex xslt xpath replace
Rectangle 27 3

If you are not replacing a single character with another single character (in which case you could use the translate function), one approach you can take to avoid writing out the xsl:call-template multiple times, is to have a template matching text() where you then do the call in one place.

<xsl:template match="text()">
<xsl:call-template name="replace-string">
  <xsl:with-param name="text" select="normalize-space(.)"/>
  <xsl:with-param name="replace" select="'/'" />
  <xsl:with-param name="with" select="'%2F'"/>
</xsl:call-template>
</xsl:template>

Then, instead of doing of using xsl:value-of to output the text (Note, that I adjusted your current expression, as for your given XML, it was actually not outputting anything)

<xsl:value-of select="normalize-space(mods:titleInfo[not(@type='alternative')][1]/mods:title)" />
<xsl:apply-templates select="mods:titleInfo[not(@type='alternative')][1]/mods:title/text()" />

Also note how this means you only have normalize-space() in one place now too.

EDIT: If you don't want to be so generic, you could make use of the mode attribute to avoid all text being changed

<xsl:template match="text()" mode="replace">
<xsl:call-template name="replace-string">
  <xsl:with-param name="text" select="normalize-space(.)"/>
  <xsl:with-param name="replace" select="'/'" />
  <xsl:with-param name="with" select="'%2F'"/>
</xsl:call-template>
</xsl:template>
xsl:apply-templates
<xsl:apply-templates select="mods:titleInfo[not(@type='alternative')][1]/mods:title/text()" mode="replace" />
mode

wont this cause problems for other elemnts that might have / in them? because of confidentiality i only included the mods elemnts that i had the problem of transforming

xml - XSLT string replace as function - Stack Overflow

xml xslt xslt-1.0
Rectangle 27 4

The translate function can't do this, it can only remove or replace single characters, not multi-character strings. Like so many things in XSLT 1.0 the escape route is a recursive template, the simplest version being:

<xsl:template name="removeWord">
  <xsl:param name="word" />
  <xsl:param name="text" />

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

And then call this template when you define the nme variable.

<xsl:variable name="nme">
  <xsl:call-template name="removeWord">
    <xsl:with-param name="word" select="'and'" /><!-- note quotes-in-quotes -->
    <xsl:with-param name="text" select="translate(Name, ',:', '')" />
  </xsl:call-template>
</xsl:variable>

Here I'm using translate to remove the single characters and then passing the result to the template to remove "and".

Though as pointed out in the comments, it depends exactly what you mean by "word" - this will remove all occurrences of the string "and" including in the middle of other words, you might want to be more conservative, removing only " and" (space-and), for example.

To remove more than one word you simply call the template repeatedly, passing the result of one call as a parameter to the next

<xsl:variable name="noEdition">
  <xsl:call-template name="removeWord">
    <xsl:with-param name="word" select="'Edition'" />
    <xsl:with-param name="text" select="translate(Name, ',:', '')" />
  </xsl:call-template>
</xsl:variable>

<xsl:variable name="nme">
  <xsl:call-template name="removeWord">
    <xsl:with-param name="word" select="' and'" />
    <xsl:with-param name="text" select="$noEdition" />
  </xsl:call-template>
</xsl:variable>

@Ian Roberts : What if i want to add one more word(multiletters) say "Edition" to the same text. Should i write another template?.

@SenthilArasu I've modified the template in my example to take the "word" as a second parameter, so you could just call it twice, passing the result of the first call to the second.

@Ian Roberts : Sorry for being such a dumb. Am not able to follow the second call. These are the two words needs to be removed ' and' ,'Edition'. Can you please modify the code now?

@SenthilArasu does that make it clearer?

@IanRoberts: I will try this . But alternatively i made changes to Template to check for words like 'and' and 'Edition'. That worked for me as well.

xml - Remove the word 'and' in XSLT using translate function - Stack O...

xml xslt xslt-1.0
Rectangle 27 4

The translate function can't do this, it can only remove or replace single characters, not multi-character strings. Like so many things in XSLT 1.0 the escape route is a recursive template, the simplest version being:

<xsl:template name="removeWord">
  <xsl:param name="word" />
  <xsl:param name="text" />

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

And then call this template when you define the nme variable.

<xsl:variable name="nme">
  <xsl:call-template name="removeWord">
    <xsl:with-param name="word" select="'and'" /><!-- note quotes-in-quotes -->
    <xsl:with-param name="text" select="translate(Name, ',:', '')" />
  </xsl:call-template>
</xsl:variable>

Here I'm using translate to remove the single characters and then passing the result to the template to remove "and".

Though as pointed out in the comments, it depends exactly what you mean by "word" - this will remove all occurrences of the string "and" including in the middle of other words, you might want to be more conservative, removing only " and" (space-and), for example.

To remove more than one word you simply call the template repeatedly, passing the result of one call as a parameter to the next

<xsl:variable name="noEdition">
  <xsl:call-template name="removeWord">
    <xsl:with-param name="word" select="'Edition'" />
    <xsl:with-param name="text" select="translate(Name, ',:', '')" />
  </xsl:call-template>
</xsl:variable>

<xsl:variable name="nme">
  <xsl:call-template name="removeWord">
    <xsl:with-param name="word" select="' and'" />
    <xsl:with-param name="text" select="$noEdition" />
  </xsl:call-template>
</xsl:variable>

@Ian Roberts : What if i want to add one more word(multiletters) say "Edition" to the same text. Should i write another template?.

@SenthilArasu I've modified the template in my example to take the "word" as a second parameter, so you could just call it twice, passing the result of the first call to the second.

@Ian Roberts : Sorry for being such a dumb. Am not able to follow the second call. These are the two words needs to be removed ' and' ,'Edition'. Can you please modify the code now?

@SenthilArasu does that make it clearer?

@IanRoberts: I will try this . But alternatively i made changes to Template to check for words like 'and' and 'Edition'. That worked for me as well.

xml - Remove the word 'and' in XSLT using translate function - Stack O...

xml xslt xslt-1.0
Rectangle 27 2

EXSLT has some good functions for you. If you need to replace simple strings, try str:replace. An XSLT 1.0 template implementation is given.

Thanks, I hadn't heard of EXSLT. It's a shame the regex EXSLT functions aren't in my version of xsltproc (on Debian) - but it turns out replace is :-) - sorry I can't accept 2 answers.

xml - How to replace multiple text substrings in XSLT 1 - Stack Overfl...

xml xslt
Rectangle 27 3

Technically, you can't replace a part of anything in XSLT. However, when you are replacing the entire value of a node, you can use string functions to utilize parts of the value being replaced when building the new value.

<xsl:template match="command">
    <xsl:copy>
        <xsl:value-of select="substring-before(., 'OLDPATH')" />
        <xsl:text>NEWPATH</xsl:text>
        <xsl:value-of select="substring-after(., 'OLDPATH')" />
    </xsl:copy>
</xsl:template>

would result in:

<command>chmod 550 NEWPATH/system</command>
<command>chmod 750 NEWPATH/system/config/home</command>

Is there a way to replace only part of the value within a node using X...

xslt
Rectangle 27 6

In my opinion, one of the most annoying things in standard XSLT (I'm talking about XSLT 1.0 because that's the only version I have used) is that it lacked support of string transformations and some basic date-time functions manipulations.

One thing I could never understand is why a function such as translate() was designed and implemented into xpath wheras other more useful functions such as replace, to_lower, to_upper, or - let's be crazy - regular expressions were not.

Some of these issues were adressed I guess with eXSLT (extended xslt ?) for parsers other than Microsoft's MSXML. I say I guess because I actually never used it as it was declared incompatible with MSXML.

I don't understand why XSLT 1.0 was designed with this principle that 'text' manipulation was not be in the scope of the language when it's obvious that whenever you are converting files you can't avoid those string conversion issues (e.g. : transform an unregularly padded date given in french format to american format, 31/1/2008 to 2008-01-31) huh...

These text manipulation issues were generally very basic and easily adressed in MSXML by allowing XSL to be extended with JScript functions : you could call a JScript function to perform some processing just as you would call any XSL template, but I always found that solution inelegant and ended up creating my own XSL template libraries. First because the JScript way broke your XSL portability, and then because it forced you to mix your programming logic : some bits in pure XPath/XSLT expression and other bits in DOM/object notation with JScript.

Not having updatable variables is another limitation that is very confusing for newcomers, some people just don't overcome this and keep struggling with that. In some simple cases you can have workarounds with a mix of paremetrized templates and recursive calls (for example to implement an increasing or decrasing counter) but let's face it, recursion is not that natural.

I think I heard all those limitations were adressed in the XSLT 2.0 specification, sadly MS decided not to implement it and promote XQuery instead. That's sad, why not implement both of them? I think that XSLT would still have a good chance of becoming as popular as CSS became for HTML. When you think about it, the most difficult part in learning XSLT is XPath, the rest is not as difficult as understanding the cascading behaviour in CSS, and CSS has become so popular...

So, in my opinon, it's the lack of all those little things mentioned here and the time it took to adress them in XSLT 2.0 (with not even MS supporting it anyway) that has lead to this situation of impopularity. How I wish MS decided to implement it after all...

xml - Why has XSLT never seen the popularity of many other languages t...

xml xslt
Rectangle 27 1

The translate() function maps from character to character. In your case, you're replacing | with (the first character), which is line feed (LF). This may work on Unix systems where LF commonly marks end of line, but it won't work on Windows, for example, where the end of line marker is CR+LF ().

I have tried implementing the recursive template and am running into a significant issue. When I implement it, the output is entirely blank. (Even erasing the rest of the output from the previously working XSL.) Thoughts?

You'd need to provide more information on how it's failing (in a new question, please, not a comment), but what's wrong with Michael's answer here to your specific question?

I am not sure why it was not working. I may have simply made a typo. Michael's solution is working. Thank you both for your help and explanation!

xml - XSLT 1.0 Translate String - Change Character to New Line - Stack...

xml xslt special-characters newline character-replacement
Rectangle 27 1

The translate function of XPath and XSLT 1.0 serves only to replace one Unicode character by another Unicode character; you can provide a list of input and replacement characters where then each character in the first list is then replaced by the one in the second list at the same position. But to replace complete works or phrases you need other tools.

You have not said or described whether you want to replace the complete attribute value, assuming that you can (with XSLT 2.0) simply do e.g.

<root>
  <foo bar="IANAL"/>
  <foo bar="WYSIWYG"/>
</root>
<root>
  <foo baz="I am not a lawyer"/>
  <foo baz="What you see is what you get"/>
</root>

If you want to do several replacements of substrings in one value or string then more effort is needed but with the replace function in XSLT/XPath 2.0 that is possible too.

Here is an example using a list of items and a recursive function replacing phrases:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs mf"
  version="2.0">

<xsl:key name="phrase" match="phrase" use="@input"/>

<xsl:function name="mf:replace-phrases" as="xs:string">
  <xsl:param name="phrases" as="element(phrase)*"/>
  <xsl:param name="text" as="xs:string"/>
  <xsl:choose>
    <xsl:when test="not($phrases)">
      <xsl:sequence select="$text"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:sequence select="mf:replace-phrases($phrases[position() gt 1], replace($text, $phrases[1]/@input, $phrases[1]/@output))"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

<xsl:param name="phrases">
  <phrases>
    <phrase input="IANAL" output="I am not a lawyer"/>
    <phrase input="WYSIWYG" output="What you see is what you get"/>
  </phrases>
</xsl:param>

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* , node()"/>
  </xsl:copy>
</xsl:template>


<xsl:template match="foo/@bar">
  <xsl:attribute name="baz" select="mf:replace-phrases($phrases/phrases/phrase, .)"/>
</xsl:template>

</xsl:stylesheet>
<root>
  <foo bar="He said: 'IANAL'. I responded: 'WYSIWYG', and he smiled."/>
</root>
<root>
  <foo baz="He said: 'I am not a lawyer'. I responded: 'What you see is what you get', and he smiled."/>
</root>

Thanks, I'm using v2, but the created attribute is always empty (in every element, even though I've only got one test phrase defined). Does the test work for you?

sry, my mistake. I wrapped a 'choose' clause arround the thing to stop non relevant values being replaced with empty strings

xml - XSL list of words to replace, most easy defintion - Stack Overfl...

xml xslt xslt-2.0