RE: [xsl] Multiple String Replacements [with a twist]

Subject: RE: [xsl] Multiple String Replacements [with a twist]
From: "Ignacio Garcia del Campo" <igarc001@xxxxxxxxxxx>
Date: Wed, 28 Mar 2007 08:35:26 -0400
I would like to use XSLT 1.0 if possible, since the idea is that IE will get the xml file and parse the output.

Here is my code (this is just a short example I created to make sure that what I wanted was possible to do, before I applied it to my real files, but if it works here I can translate it)

XSLT FILE:
---------------
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0">
<!-- reusable replace-string function -->


<xsl:template name="replace-string">
   <xsl:param name="text"/>
   <xsl:param name="from"/>
   <xsl:param name="to"/>

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

</xsl:template>


<xsl:template name="replace-strings"> <xsl:param name="text" /> <xsl:param name="changes" /> <xsl:param name="count" />

	<xsl:param name="returnString">
		<xsl:call-template name="replace-string">
			<xsl:with-param name="text" select="$text"/>
			<xsl:with-param name="from" select="$changes/change[$count]/text" />
			<xsl:with-param name="to" select="$changes/change[$count]/link" />
		</xsl:call-template>
	</xsl:param>

	<xsl:if test="$count > 1">
		<xsl:call-template name="replace-strings">
			<xsl:with-param name="text">
				<xsl:copy-of select="$returnString" />
			</xsl:with-param>
			<xsl:with-param name="changes" select="$changes" />
			<xsl:with-param name="count" select="$count - 1" />
		</xsl:call-template>
   </xsl:if>

	<xsl:if test="$count = 1">
		<xsl:copy-of select="$returnString" />
	</xsl:if>
</xsl:template>


<!-- test the function -->


<xsl:template match="/">
 <html>
 <body>
 <h2>My Collection</h2>
   <table border="1">
     <tr bgcolor="#9acd32">
       <th align="left">Title</th>
       <th align="left">Artist</th>
		<th align="left">Change#</th>
     </tr>
     <xsl:for-each select="catalog/cd">
     <tr>
       <td>
			<xsl:choose>
				<xsl:when test="count(changes/change) > 0">
					<xsl:call-template name="replace-strings">
			        <xsl:with-param name="text"
			             select="title"/>
			        <xsl:with-param name="changes" select="changes"/>
					<xsl:with-param name="count" select="count(changes/change)" />
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="title" />
				</xsl:otherwise>
			</xsl:choose>
		</td>
       <td><xsl:value-of select="artist"/></td>
		<td>
			<xsl:value-of select="count(changes/change)" />
		</td>
     </tr>
     </xsl:for-each>
   </table>
 </body>
 </html>
</xsl:template>

<xsl:template match="NewTemplate">

</xsl:template>
</xsl:stylesheet>
-------------------------------------

XML FILE:
--------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="cdcatalog_test.xsl" ?>
<catalog>
	<cd>
		<title>The [[Fire]] of [[Athens]]</title>
		<artist>John Lewis</artist>
		<country>USA</country>
		<company>Columbia</company>
		<price>10.90</price>
		<year>1985</year>
		<changes>
			<change>
				<text>[[Fire]]</text>
				<link><a href="http://en.wikipedia.org/wiki/Fire";>Fire</a></link>
			</change>
			<change>
				<text>[[Athens]</text>
				<link><a href="http://en.wikipedia.org/wiki/Athens";>Athens</a></link>
			</change>
		</changes>
	</cd>
	<cd>
		<title>Hide your heart</title>
		<artist>Bonnie Tyler</artist>
		<country>UK</country>
		<company>CBS Records</company>
		<price>9.90</price>
		<year>1988</year>
		<changes/>
	</cd>
	<cd>
		<title>Greatest Hits</title>
		<artist>Dolly Parton</artist>
		<country>USA</country>
		<company>RCA</company>
		<price>9.90</price>
		<year>1982</year>
		<changes/>
	</cd>
</catalog>
-------------------------------------------------

I placed the [[ ]] around the words I want replaced, because in my actual files there are instances that have to be replaced and others that don't, so I will add some kind of character code to differenciate them.

Thank you.

From: "Michael Kay" <mike@xxxxxxxxxxxx>
Reply-To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Subject: RE: [xsl] Multiple String Replacements [with a twist]
Date: Wed, 28 Mar 2007 00:13:25 +0100

If you can use XSLT 2.0, then xsl:analyze-string is the perfect answer to
this problem.

It's possible but tedious to do it with XSLT 1.0 using recursive templates.
It's difficult to tell you what you're doing wrong since you haven't shown
us your code.

Michael Kay
http://www.saxonica.com/

> -----Original Message-----
> From: Ignacio Garcia del Campo [mailto:igarc001@xxxxxxxxxxx]
> Sent: 27 March 2007 19:56
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Multiple String Replacements [with a twist]
>
> Hello all,
>
> I just started working with XSLT and I find my self stuck on
> this issue.
>
> I want to replace multiple strings for some for most of my
> elements and by looking at some discussions and some code by
> Jeni Tennison I can replace all instances of my strings by a
> simple replacement. However, what I actually want to do, is
> to replace the strings by links.
>
> My replacements look like this:
>
> <foo:string_replacements>
>
>   <foo:search>
>
>      <foo:find>XML</foo:find>
>
>      <foo:replace><a href="xml.com">XML-SITE</a></foo:replace>
>
>   </foo:search>
>
> </foo:string_replacements>
>
> If I use <xlst:copy-of select="foo:search[xx]/replace" /> the
> HTML shows the link correctly, but since I am doing multiple
> substitions of multiple strings I use recursion, and the
> function where the strings are exchanged fails to correctly
> place the anchor code on the output.
>
> I get XML replaced by XML-SITE but the anchor information is
> lost in the process.
>
> I have tried using CDATA sections, but then as you might
> expect I get the escaped string and that's not good either.
>
> Does anyone know how to solve this problem?
>
> I have been using something similar to this:
> http://sources.redhat.com/ml/xsl-list/2000-06/msg00200.html,
> but I need the links to be working.
>
>
>
> Thanks.

Current Thread