Bad wording on the question, sorry about that. Will try to explain what I'm trying to do. Basically I have the output from a search as Xml and in that Xml there is a node like this one:
<FIELD NAME="body">
Somebody named
<key>Doris</key>
and
<key>Arnie</key>
</FIELD>
In short, what I need is to replace "<key>" with "<strong>"; ie. highlight the search hits (the key node values are what the user searched for). In the Xslt I do not know what the user searched from, other than querying the Xml -> FIELD[@name='body']/key.
Right now I have some crazy code that will extract whatever is in front of the search term ("Doris"), but that ony works for 1 search term. We need it to do this for multiple terms. The code we use looks like this:
<xsl:template name="highlighter">
<xsl:param name="text"/>
<xsl:param name="what"/>
<xsl:choose>
<xsl:when test="contains($text, $what) and string-length($what) > 0">
<xsl:variable name="before" select="substring-before($text, $what)"/>
<xsl:variable name="after" select="substring-after($text, $what)"/>
<xsl:variable name="real-before" select="substring($text, 1, string-length($before))"/>
<xsl:variable name="real-what" select="substring($text, string-length($before) + 1, string-length($what))"/>
<xsl:variable name="real-after" select="substring($text, string-length($before) + string-length($what) + 1)"/>
<xsl:value-of select="$real-before"/>
<strong>
<xsl:value-of select="$real-what"/>
</strong>
<xsl:call-template name="highlighter">
<xsl:with-param name="text" select="$real-after"/>
<xsl:with-param name="what" select="$what"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
What I've been trying to do is to call this code multiple times with the different search terms, but I'm struggeling on how to use the output from the call to the template as input to the next call. In code it would be something like this:
string body = doc.SelectSingleNode("FIELD[@NAME='body']");
NodeCollection nodes = doc.SelectNodes("FIELD[@NAME='body']/key");
foreach (var node in nodes) {
body = hightlighter(body, node.InnerText);
}
So far I have been unable to do something like this in XSLT, but I'm still a noob so... ;)
Edit: Just to clarify; the output I'm looking for is this:
Somebody named <strong>Doris</strong> and <strong>Arnie</strong>
This should do what you need. It uses the apply template instead of calling templates and is more of a functional way to tackle this problem.
Why can't you just replace the "KEY" element with "STRONG" elements? Better not to think too imperatively about this.
Or did I misunderstand you?
The best thing to do in such situations is to recursively copy nodes from input to output and override the nodes that you want to treat differently. The key idea is that the text strings are nodes which can be copied too. Here's an example: