Re: [xsl] Placing mark-up in between strings

Subject: Re: [xsl] Placing mark-up in between strings
From: Jeff Sese <jsese@xxxxxxxxxxxx>
Date: Thu, 23 Nov 2006 16:53:39 +0800
I have tried this template:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; xmlns:xs="http://www.w3.org/2001/XMLSchema"; xmlns:ati="http://www.asiatype.com/xslt-functions"; exclude-result-prefixes="xs ati">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:template name="start">
<xsl:variable name="input-str" as="xs:string" select="'This is supposed to be my input string with search1, search2, and search3. There is another search1.'"/>
<xsl:variable name="search-str" as="xs:string*" select="('search1','search2','search3')"/>
<xsl:variable name="replace-str" as="xs:string*" select="('replace1','replace2','replace3')"/>
<p><xsl:sequence select="ati:tag($input-str, $search-str, $replace-str)"/></p>
</xsl:template>
<xsl:function name="ati:tag" as="node()+">
<xsl:param name="input-str" as="xs:string"/>
<xsl:param name="search-str" as="xs:string*"/>
<xsl:param name="replace-str" as="xs:string*"/>
<xsl:choose>
<xsl:when test="exists($search-str)">
<xsl:value-of select="substring-before($input-str, $search-str[1])"/>
<replacement value="{$replace-str[1]}"><xsl:sequence select="$search-str[1]"/></replacement>
<xsl:sequence select="ati:tag(substring-after($input-str, $search-str[1]),remove($search-str,1),remove($replace-str,1))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$input-str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>


And got this output:

<?xml version="1.0" encoding="UTF-8"?>
<p>This is supposed to be my input string with <replacement value="replace1">search1</replacement>, <replacement value="replace2">search2</replacement>, and <replacement value="replace3">search3</replacement>. There is another search1.</p>


My template will only tag the first occurrence of the search string, because i'm using substring-before and substring-after approach. Also, i want to avoid placing mark-ups to the search string that is already marked-up. Example i don't want this to happen.

<p>This is supposed to be my input string with <replacement value="replace1"><replacement value="replace1">search1</replacement></replacement>, <replacement value="replace2">search2</replacement>, and <replacement value="replace3">search3</replacement>. There is another <replacement value="replace1">search1</replacement>.</p>

That's why i don't want to loop back to the start of the string. I was thinking of using this, '<replacement value="replace1">search1</replacement>', as the replacement string and then just us d-o-e, but i want to avoid using d-o-e because there might be part of the string that i don't want to do d-output-e.

Is there any alternative solution to this?

-- Jeff

Jeff Sese wrote:
Hi,

I have this function (thanks to sir M. Kay) that search and replaces all occurrences of a sequence of search string with its corresponding replacement string.

<xsl:function name="ati:replace-all">
<xsl:param name="input" as="xs:string"/>
<xsl:param name="words-to-replace" as="xs:string*"/>
<xsl:param name="replacement" as="xs:string*"/>
<xsl:sequence select="if (exists($words-to-replace)) then ati:replace-all(replace($input, $words-to-replace[1], $replacement[1]),remove($words-to-replace,1),remove($replacement,1)) else $input"/>
</xsl:function>


Can this be modified so that I can place the search string inside an element and the replacement string inside an attribute?

I have this as a sample:

<p>This is supposed to be my input string with search1, search2, and search3.</p>

I want this to be:

<p>This is supposed to be my input string with <replacement value="replacement1">search1</replacement>, <replacement value="replacement2">search2</replacement>, and <replacement value="replacement3">search3</replacement>.</p>

Thanks,
Jeff

Current Thread