[xsl] XSL - avoiding code duplication

Subject: [xsl] XSL - avoiding code duplication
From: Jason Varsoke <jvarsoke@xxxxxxxxx>
Date: Mon, 26 May 2003 07:07:53 -0700 (PDT)
I'm trying to cut down on the duplication of XML and XSL in my
project.  In the XML I have a few common nodes that are referenced by
children of other more specific nodes.  For example:
---XML---
<common id="foo">
   <data attribute="bar"/>
</common>
<specific name="joe">
   <commonref refid="foo"/>
</specific>
---XML----
Now I do this because "common" usually has lots of generic data that I
use over and over again.  But occationally I want to override some of
that data for one of the "specific"s.  For example I might do
<commonref refid="foo" attribute="baz"/> where I want to use all the
data from <common> but replace that one attribute with something
specific.
So I have this set up in my XML data files.  And I have it working as
follows in my XSL.
---XSL---
<xsl:template match="commonref" mode="quux">
  <xsl:variable name="attribute">
      <xsl:choose>
         <xsl:when test="@attribute">
            <xsl:value-of select="@attribute"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="id(@idref)/@attribute"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:variable>
</xsl:template>
---XSL---
So the above creates a variable $attribute that either contains
<specific>'s version of "attribute" if it is set, or <common>'s
version of "attribute" if a specific one hasn't been set.
Now to the problem: I have several "mode" templates and for each of
them I need copy this code.  I'm not very fond of this kind of
cut-and-paste development so I tried to write a call-template function
to manage these variables, however, if I do that the scope of the
variables doesn't reach my mode function.  For example:
<xsl:template match="commonref" mode="quux">
   <xsl:call-template name="set-vars">
       <xsl:with-param name="node" select="."/>
   </xsl:call-template>
   <xsl:value-of select="$attribute"/>
</xsl:template>
<xsl:template name="set-vars">
  <xsl:param name="node/>
  <xsl:variable name="attribute">
      <xsl:choose>
         <xsl:when test="node/@attribute">
            <xsl:value-of select="node/@attribute"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="id(node/@idref)/@attribute"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:variable>
</xsl:template>
Does not work and gives an error that the variable is out of scope. 
Sensible.  But my question is how to I compartmentalize this code so I
don't have to cut-and-paste it all over the place (btw there are about
5 variables I need to do this with each time -- so the c-n-p is a lot
more than it seems here).
Suggestions?
-j



__________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo.
http://search.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread