xsl-list
[Top] [All Lists]

Re: search and replace

2004-04-29 06:57:22
Hi Norma,

I found this template on the list but am not sure how to implement
it. I'm trying to replace ??degrees?? with ° in all xml tags.
Is it possible and can someone explain how this template
would/should work?

I've tried a few variations and I keep getting an error that
call-template not allowed in stylesheet message.

I think that the error's arising because you've got the
<xsl:call-template> element at the top level of your stylesheet. It
can only appear within a template. Since you want to make the
replacement inside all the elements in your document, I suggest having
a template that matches all text nodes, and putting the template call
within that:

<xsl:template match="text()">
  <xsl:call-template name="_replace_string">
    <xsl:with-param name="string" select="." />
    <xsl:with-param name="find" select="'??degrees??'" />
    <xsl:with-param name="replace" select="'&#xB0;'" />
  </xsl:call-template>
</xsl:template>

Make sure that the templates that you have to process the elements
contain a <xsl:apply-templates> instruction to process their text node
children rather than a <xsl:value-of> instruction, otherwise this
template won't get used.

The <xsl:call-template> in the above template calls the template with
$string set to the value of the text node, $find set to the string
'??degrees??' and $replace set to the string '&#xB0;' (the degree
sign, I assume).

The _replace_string template is a recursive template that replaces all
the instances of $find in $string with $replace. It first tests to see
whether $string contains $find or not; if not, then all it has to do
is output $string itself.

<xsl:choose>
  <xsl:when test="contains($string,$find)">
[snip]
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="$string"/>
  </xsl:otherwise>
</xsl:choose>

If $string *does* contain $find, then the template identifies the
substring before $find with substring-before($string, $find) and
outputs that, concatenated with the $replace string.

<xsl:value-of
  select="concat(substring-before($string,$find),$replace)"/>

Then the template moves on to the next part of the string, the
substring after the first instance of $find in $string. It calls the
template again, but with a different value for $string (this is the
recursive call):

<xsl:call-template name="_replace_string">
  <xsl:with-param name="string"
    select="substring-after($string,$find)"/>
  <xsl:with-param name="find" select="$find"/>
  <xsl:with-param name="replace" select="$replace"/>
</xsl:call-template>

I hope this explains things; come back to us with any questions.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



<Prev in Thread] Current Thread [Next in Thread>