[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Text replacement using "recursion"

Subject: Text replacement using "recursion"
From: TeleServices <teleservices@xxxxxxxxx>
Date: Mon, 22 Oct 2007 11:40:10 -0700
 Text replacement using "recursion"
I have a reporting system that merges three xml sources:

 1) boilerplate - text seen in all reports
 2) custom - text that is used to replace "phrase" elements in boilerplate
 3) vars - values (text or numbers) used to select from custom text

This works fine unless I wish to put a "phrase" element inside another
"phrase" element.  I originally did the "flat" version" with an
implication that in future I would allow "recursion" (phrases inside
phrases).

Well I bit off a little more than I bargained for because I do not
seem to understand how to get this type of "recursion" to work.

Note, that there are several ways this is used.  This can be seen in
the examples.  I can expound on this if need be - I am trying to keep
this very simple to start with.

Following my message are example files:

  1)  boilerplate.xml - For simplicity I have combined boilerplat.xml,
      custom.xml and vars.xml into this one file - normally they are
      passed as pararmeters (it get same results).
  2a) merge.xsl (original version) - merges the three sources
  2b) merge.xsl (attempt at "recursion") - merges the three sources
  3)  present.xsl - present report.xml as HTML file report.htm to
      view results as user would see them.

I have been using command line tols to test this problem.

To create the report.xml file I process these files I am using
msxsl.exe under Windows:

  msxsl boilerplate.xml merge.xsl > report.xml

or xsltproc under linux:

  xsltproc merge.xsl boilerplate.xml >report.xml

To present the report.xml as an HTML file report.htm, I use one of
these commands. For Windows:

  msxsl report.xml present.xsl > report.htm

for linux:

  xsltproc present.xsl report.xml >report.htm


So, can anyone help me understand how to process a "phrase" inside a "phrase"?

Also, any critiques or suggestion about my code are most welcome as I
am bit of a newbie.

Thanks for any help!

Dan Vokt, Teleservices

==== FILES ARE BELOW ======================================

1) boilerplate, custom, vars:
---- boilerplate.xml -----------------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<report>
<vars> <!-- vars.xml generated at runtime -->
 <var name="var1">value1</var>
 <var name="var2">value2</var>
 <var name="var3">value3</var>
 <var name="var4">value4</var>
</vars>

<lists> <!-- custom.xml -->
 <list name="keyword-list">
  <option id="value1">VALUE_1</option>
  <option id="value2">VALUE_2</option>
  <option id="value3">VALUE_3</option>
  <option id="value4">VALUE_4</option>
 </list>
 <list name="phrase-list">
  <option id="value1">this is phrase list item 1 from phrase-list</option>
  <option id="value2">this is phrase list item 2 from phrase-list</option>
  <option id="value3">this is phrase list item 3 from phrase-list</option>
  <option id="value4">this is phrase list item 4 from phrase-list</option>
 </list>
 <list name="phrase-list-recursive">
  <option id="value1">this is phrase list item 1 from
phrase-list-recursive, with a value of '<phrase name="var1"/>' for
var1</option>
  <option id="value2">this is phrase list item 2 from
phrase-list-recursive, with a value of '<phrase name="var1"/>' for
var1</option>
  <option id="value3">this is phrase list item 3 from
phrase-list-recursive, with a value of '<phrase name="var1"/>' for
var1</option>
  <option id="value4">this is phrase list item 4 from
phrase-list-recursive, with a value of '<phrase name="var1"/>' for
var1</option>
 </list>
</lists>

<h4>name to value:</h4> <!-- boilerplate.xml -->
Your var1 value of <phrase name="var1"/> is very interesting, though
not as interesting as the <phrase name="var4"/> value of your var4.<br
/>
<h4>name to keyword:</h4>
Your var1 keyword of <phrase name="var1" list="keyword-list"/> is very
interesting, though not as interesting as the <phrase name="var4"
list="keyword-list"/> keyword of your var4.<br />
<h4>name to phrase:</h4>
Your var1 phrase of <phrase name="var1" list="phrase-list"/> is very
interesting, though not as interesting as the <phrase name="var4"
list="phrase-list"/> phrase of your var4.<br />
<h4>name to phrase-recursive -- PROBLEM!!!:</h4>
Your var1 recursive phrase of <phrase name="var1"
list="phrase-list-recursive"/> is very interesting, though not as
interesting as the <phrase name="var4" list="phrase-list-recursive"/>
recursive phrase of your var4.<br />
</report>
--------------------------------------------------------------------------

2a) Here is the ORIGINAL XSL file that merges these:
---- merge.xsl (original) ------------------------------------------------
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="report"/>

<!-- original -->
<xsl:template match="phrase">
<span class="phrase">
 <xsl:variable name="phrase" select="@name"/>
 <xsl:variable name="list">
  <xsl:choose>
    <xsl:when test="@list"><xsl:value-of select="@list"/></xsl:when>
    <xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
  </xsl:choose>
 </xsl:variable>
 <xsl:variable name="var" select="//vars/var[@name=$phrase]/text()"/>
 <xsl:variable name="verbiage"
select="//lists/list[@name=$list]/option[@id=$var]"/>
 <xsl:if test="string-length($verbiage)>0"><xsl:value-of
select="$verbiage"/></xsl:if>
 <xsl:if test="string-length($verbiage)=0"><xsl:value-of
select="$var"/></xsl:if>
</span>
</xsl:template>


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

<!-- do not directly process vars or lists -->
<xsl:template match="vars"/>
<xsl:template match="lists"/>
</xsl:stylesheet>
--------------------------------------------------------------------------

2b) Here is my lame ATTEMPT at "recursion":
---- merge.xsl ("recursive") ---------------------------------------------
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="report"/>

<xsl:template match="phrase">
 <xsl:variable name="phrase-name" select="@name"/>
 <xsl:variable name="list">
  <xsl:choose>
    <xsl:when test="@list"><xsl:value-of select="@list"/></xsl:when>
    <xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
  </xsl:choose>
 </xsl:variable>
 <xsl:variable name="var" select="//vars/var[@name=$phrase-name]/text()"/>
 <xsl:variable name="verbiage"
select="//lists/list[@name=$list]/option[@id=$var]"/>
 <xsl:variable name="phrase">
  <xsl:choose>
    <xsl:when test="string-length($verbiage)>0"><xsl:value-of
select="$verbiage"/></xsl:when>
    <xsl:otherwise><xsl:value-of select="$var"/></xsl:otherwise>
  </xsl:choose>
 </xsl:variable>
<span class="phrase">
 <xsl:value-of select="$phrase"/>
 <xsl:if test="//vars/var[@name=$phrase-name]/phrase">
  <xsl:apply-templates select="//vars/var[@name=$phrase-name]/phrase"/>
 </xsl:if>
 <xsl:if test="//lists/list[@name=$list]/option[@id=$var]/phrase">
  <xsl:apply-templates
select="//lists/list[@name=$list]/option[@id=$var]/phrase"/>
 </xsl:if>
</span>
</xsl:template>

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

<!-- do not directly process vars or lists -->
<xsl:template match="vars"/>
<xsl:template match="lists"/>
</xsl:stylesheet>
--------------------------------------------------------------------------

3) I present the report.xml as an HTML file report.htm using this:
---- present.xsl ---------------------------------------------------------
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" indent="yes" encoding="utf-8"/>

<xsl:template match="/">
 <html>
 <head>
  <title>Simple Recursive Phrase</title>
  <style>
  p {
     margin-top: 0;
  }
  h4 {
     margin-bottom: .5em;
  }
  .phrase {
     color:blue;
   }
  .phrase .phrase {
     color:red;
   }
  .phrase .phrase .phrase {
     color:green;
   }
  .phrase .phrase .phrase .phrase {
     color:magenta;
   }
  </style>
 </head>
 <body><xsl:apply-templates/></body>
 </html>
</xsl:template>

<xsl:template match="para">
 <xsl:if test="@title!=''">
  <h4 class="paratitle"><xsl:value-of select="@title"/></h4>
 </xsl:if>
 <p><xsl:apply-templates/></p>
</xsl:template>

<xsl:template match="a|ul|li|img|table|tr|td|span|div|pre|label|h4">
 <xsl:copy><xsl:copy-of select="@*"/>
 <xsl:apply-templates/>
 </xsl:copy>
</xsl:template>

<xsl:template match="br"><br /></xsl:template>

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

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.