Re: [xsl] Replace Escapes

Subject: Re: [xsl] Replace Escapes
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Wed, 15 Nov 2006 09:49:13 +0000
Hi Senthilkumaravelan,

I have difficulty in recursive replacement of escapes.

Thanks for showing your sample XML and desired output so clearly. One thing confuses me, though: your sample XML contains element names that are escaped with both double square brackets, such as [[BUYERS_NAME]] and single ones, such as [WEB_ORDER_NUMBER]. I'm going to assume you just want to use single square brackets.


First, I'd set up a key that holds the elements that hold the values you want to insert, such as <BUYERS_NAME>.

<xsl:variable name="replacements"
              select="/broadcast/ORDER_FEED/ORDER/ORDER_HEADER/*" />

Then I'd write a recursive template that takes a string, looks for the first [, and outputs the string up to the first [, then the replacement value for the substring between the first [ and the next ], and finally calls itself on the substring after the ]:

<xsl:template name="replace-escapes">
  <xsl:param name="string" />
  <xsl:choose>
    <xsl:when test="contains($string, '[')">
      <!-- substring before the escaped sequence -->
      <xsl:value-of select="substring-before($string, '[')" />

      <!-- replacement for the string between the []s -->
      <xsl:variable name="ename"
        select="substring-before(substring-after($string, '['), ']')" />
      <xsl:value-of select="$replacements[name() = $ename]" />

      <!-- recursive call on the rest of the string -->
      <xsl:call-template name="replace-escapes">
        <xsl:with-param name="string"
          select="substring-after(substring-after($string, '['), ']')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

I'd call this template from a template matching text nodes in the <content> of your XML. I'd use a 'copy' mode to copy all the elements in this <content> while escaping the text. The templates would look something like:

<xsl:template match="broadcast">
  <xsl:apply-templates select="content_vars/content/*"
                       mode="copy" />
</xsl:template>

<xsl:template match="*" mode="copy">
  <xsl:copy>
    <xsl:copy-of select="@*" />
    <xsl:apply-templates mode="copy" />
  </xsl:copy>
</xsl:template>

<xsl:template match="text()" mode="copy">
  <xsl:call-template name="replace-escapes">
    <xsl:with-param name="string" select="." />
  </xsl:call-template>
</xsl:template>

You could use keys instead of a global variable holding the replacement values, but I hope this gets you on the right track.

Cheers,

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

Current Thread