7

I need to perform a find and replace using XSLT 1.0 which is really suited to regular expressions. Unfortunately these aren't available in 1.0 and I'm also unable to use any extension libraries such as EXSLT due to security settings I can't change.

The string I'm working with looks like:

19;#John Smith;#17;#Ben Reynolds;#1;#Terry Jackson

I need to replace the numbers and ; # characters with a ,. For example the above would change to:

John Smith, Ben Reynolds, Terry Jackson

I know a recursive string function is required, probably using substring and translate, but I'm not sure where to start with it.

Does anyone have some pointers on how to work this out? Here's what I've started with:

<xsl:template name="TrimMulti">
    <xsl:param name="FullString" />
    <xsl:variable name="NormalizedString">
        <xsl:value-of select="normalize-space($FullString)" />
    </xsl:variable>
    <xsl:variable name="Hash">#</xsl:variable>
    <xsl:choose>
        <xsl:when test="contains($NormalizedString, $Hash)">
            <!-- Do something and call TrimMulti -->
        </xsl:when>
    </xsl:choose>
</xsl:template>
Alex Angas
  • 59,219
  • 41
  • 137
  • 210

2 Answers2

10

I'm hoping you haven't simplified the problem too much for asking it on SO, because this shouldn't be that much of a problem.

You can define a template and recursively call it as long as you keep the input string's format consistent.

For example,

<xsl:template name="TrimMulti">
  <xsl:param name="InputString"/>
  <xsl:variable name="RemainingString" 
    select="substring-after($InputString,';#')"/>
  <xsl:choose>
    <xsl:when test="contains($RemainingString,';#')">
      <xsl:value-of 
        select="substring-before($RemainingString,';#')"/>
      <xsl:text>, </xsl:text>
      <xsl:call-template name="TrimMulti">
        <xsl:with-param 
          name="InputString"
          select="substring-after($RemainingString,';#')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$RemainingString"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

I tested this template out with the following call:

<xsl:template match="/">
  <xsl:call-template name="TrimMulti">
    <xsl:with-param name="InputString">19;#John Smith;#17;#Ben Reynolds;#1;#Terry Jackson</xsl:with-param>
  </xsl:call-template>
</xsl:template>

And got the following output:

John Smith, Ben Reynolds, Terry Jackson

Which seems to be what you're after.

The explanation of what it is doing is easy to explain if you're familiar with functional programming. The InputString parameter is always in the form [number];#[name];#[rest of string]. Each call of the TrimMulti template chops off the [number];# part and prints off the [name] part, then passes the remaining expression to itself recursively.

The base case is when InputString is in the form [number];#[name], in which case the RemainingString variable won't contain ;#. Since we know this is the end of the input, we don't output a comma this time.

Welbog
  • 59,154
  • 9
  • 110
  • 123
  • Not simplified, but I have trouble knowing where to start with the more advanced XSLT stuff! I don't work with it often. – Alex Angas Jun 25 '09 at 14:34
  • @Alex Angas: Yeah, XSLT + string manipulation = a pain in the ass. Luckily in your particular case the names aren't very hard to parse out. I've seen much worse. – Welbog Jun 25 '09 at 14:37
  • What about translate(a,b,c) -- can it be used to simplify some of the replacement? – Casey Sep 15 '10 at 07:45
-1

If the ';' and '#' characters are not valid in the input because they are delimiters then why wouldn't the translate function work? It might be ugly (you have to specify all valid characters in the second argument and repeat them in the third argument) but it would be easier to debug.

translate($InputString, ';#abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUZ0123456789,- ', ', abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUZ0123456789,- ')
Don
  • 1
  • How do you know you have listed all the valid characters? You don't. Even if you did, it's a major fail because the list might change. Can we spell UTF-8? – itsbruce Oct 29 '12 at 10:38