[xsl] Doubly recursive find/replace from list problem

Subject: [xsl] Doubly recursive find/replace from list problem
From: "thei" <thei@xxxxxxxxx>
Date: Sun, 11 Jul 2004 14:27:44 +1000
Hello,

I've come back to a previous problem that I'd abandoned as too hard, and
would like a bit of help, as I'm not getting anywhere.

I have an XML journal source, and an XML list of acronyms. I wish to
automatically replace any occurrence of an acronym within the XML
source, with the appropriate <acronym title="blah">acronym</acronym>
tag. It's easy to replace one acronym, using simple XSL recursive
find/replace, but when I try to do more than one, I hit multiple
difficulties. The ways I've tried all involve a for-all acronyms in the
acronym list, replace acronyms in the source, but the more I try, the
harder it gets. I'm having two main problems. First problem: how to not
replace acronyms within acronyms or their descriptions (I could possibly
ignore this by ensuring an acronym never appears within an acronym
description). Second and main problem: how to recursively call a
template with a different value each time, a specified number of times,
when this template already recursively calls itself an arbitrary number
of times - so I tried using recursively calling templates that call
another recursively calling template, and about that time I gave up.
Here's attempt 800 or so to give an idea of what I've been trying:


<xsl:template name="acronym">
  <xsl:param name="text"/>
  <!-- This is the list of acronyms, so for each acronym in the list -->
  <xsl:for-each
select="document('../xml/acronyms.xml')/acronyms/acronym">
    <xsl:call-template name="replace-acronym">
      <xsl:with-param name="text" select="$text"/>
      <xsl:with-param name="acr" select="string(@acronym)"/>
    </xsl:call-template>
  </xsl:for-each>
  <xsl:value-of select="$text"/>
</xsl:template>
<!-- Replace acronyms -->
<xsl:template name="replace-acronym">
  <xsl:param name="text"/>
  <xsl:param name="acr"/>
  <xsl:choose>
    <xsl:when test="contains($text,$acr)">
      <xsl:variable name="text">
        <xsl:value-of select="substring-before($text,$acr)"/>
        <!-- Construct the acronym -->
        <xsl:text disable-output-escaping="yes">&lt;acronym
title="</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text disable-output-escaping="yes">"></xsl:text>
        <xsl:value-of select="@acronym"/>
        <xsl:text disable-output-escaping="yes">&lt;/acronym></xsl:text>
      </xsl:variable>
      <xsl:call-template name="acronym">
        <xsl:with-param name="text"
select="substring-after($text,$acr)"/>
        <xsl:with-param name="acr" select="$acr"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="text" select="$text"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

I know this doesn't work, and doesn't make much sense, but it will
hopefully give you an idea of what I've been trying to do. I've been
attempting to use the template "acronym" to call the template
"replace-acronym" recursively, that is, for the first acronym, it should
call "replace-acronym" with the original text, and replace all
occurrences of that acronym within the original text, but then for the
second acronym, it should call "replace-acronym" with the text from the
first call, and replace all acronyms within this text, and so forth
until the end of the acronym list is reached. This sounds horribly
inefficient, but it's the only way I've been able to think of - except I
can't work out how to do it.

Any help would be greatly appreciated, thanks.

Printed on 100% recycled electrons.
http://nedmartin.org

Current Thread