This is the mail archive of the
docbook-apps@lists.oasis-open.org
mailing list .
Re: DSSSL -> XSL
- To: Norman Walsh <ndw at nwalsh dot com>
- Subject: Re: DOCBOOK-APPS: DSSSL -> XSL
- From: Alex Lancaster <alexl at bigfoot dot com>
- Date: 27 May 2000 01:05:39 -0600
- References: <cfg0slm772.fsf@lucero.santafe.edu> <87snve23x6.fsf@nwalsh.com>
>>>>> "NW" == Norman Walsh <ndw@nwalsh.com> writes:
NW> Ah! It took a few minutes, but I figured it out :-) When you
NW> apply-templates in this template, you go back to the "default
NW> mode". (Modes aren't sticky in XSL.)
Thanks Norm,
Yep, I discovered that modes work differently in XSL than DSSSL,
although even if you carefully apply the modes in the `mode-d'
templates recursively, you don't get the expected behaviour.
An even *more* significant difference seems to be that once in a mode
in XSL, that's where you stay, unless a further template explicitly
takes you out of it (note that this is in *contrast* to DSSSL where if
an element encountered in processing a subtree *isn't* explicity
defined inside that mode, you get the default, i.e. imported mode).
AL> <!-- template (1) -->
AL> <xsl:template match="*" mode="programmer-info-mode">
AL> <xsl:text>Running wildcard template for mode: </xsl:text><br/>
AL> <xsl:apply-templates select="."/>
AL> </xsl:template>
NW> So when corpauthor is encountered, you're no longer in
NW> programmer-info-mode.
Yep, I finally figured out that as well. Note how this is quite
different to a DSSSL construction rule, because you don't need a
`default' rule, since if you process a node with in a particular mode,
you can still access the default rules if you haven't overriden them
by an XSL template.
So the DSSSL:
(element variablelist
(let ((role (attribute-string (normalize "role"))))
(if (equal? role "programmers")
(with-mode programmer-info-mode
(process-children))
(process-children))))
(mode programmer-info-mode
(element corpauthor
(make sequence
($bold-italic-seq$ (literal "Group: "))
(process-children)))
(element fax
(make sequence
($italic-seq$ (literal "fax: "))
(process-children))))
is not equivalent to the XSL (which you might reasonably expect to
duplicate the DSSSL output):
<xsl:template match="variablelist">
<xsl:choose>
<xsl:when test="@role='programmers'">
<xsl:apply-templates mode="programmer-info-mode"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>Applying imports:</xsl:text><br/>
<xsl:apply-imports/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="corpauthor" mode="programmer-info-mode">
<b><i><xsl:text>Group: </xsl:text></i><b>
<xsl:apply-templates select="." mode="programmer-info-mode"/>
</xsl:template>
<xsl:template match="fax" mode="programmer-info-mode">
<i><xsl:text>Fax: </xsl:text></i>
<xsl:apply-templates select="." mode="programmer-info-mode"/>
</xsl:template>
NW> The interesting thing is that if I change your xsl:include to
NW> xsl:import and change this to xsl:apply-imports, then it seems to
NW> work (at least in XT). I can't decide if I think this is a bug or
NW> a feature.
Interesting, I tried with various combinations of
xsl:include/xsl:import and nothing worked in the expected way. In any
case I came up with (hopefully!) more elegant solution than my
original attempt, that avoids modes all together. Here's what I
posted to the Mulberrytech XSL list:
Solution:
---------
Search for the all the desired nodes `corpauthor', `fax', `author' in
the following example that have as _ancestors_ (arbitrarily deep), a
`variablelist' with the appropriate attribute set, so I have templates
like the following:
<!-- rules for role subclassing on programmer info pages -->
<xsl:template match="variablelist[@role='programmers']//corpauthor">
<strong><em>
<xsl:text>Group: </xsl:text>
</em></strong>
<xsl:apply-templates/><br></br>
</xsl:template>
<xsl:template match="variablelist[@role='programmers']//fax">
<em>fax: </em><xsl:apply-templates/><br></br>
</xsl:template>
Perhaps not the most efficient in terms of the processing time (if
someone could suggest an alternative, faster way, I'd love to hear
about it), but the most elegant _I_ could come up with in XSL and
certainly the most isomorphic to (and arguably more succinct in terms
of number of lines than) the DSSSL equivalent:
(element variablelist
(let ((role (attribute-string (normalize "role"))))
(if (equal? role "programmers")
(with-mode programmer-info-mode
(process-children))
(process-children))))
(mode programmer-info-mode
(element corpauthor
(make sequence
($bold-italic-seq$ (literal "Group: "))
(process-children)))
(element fax
(make sequence
($italic-seq$ (literal "fax: "))
(process-children))))
Let me also say, coming from a DSSSL background it was less than
obvious how to solve this, since modes (although superficially
similar) function in fundamentally different ways in the two
languages.
So I hope this belated followup helps others on the same migration
path.
Alex
--
Alex Lancaster * alexl@bigfoot.com * www.santafe.edu/~alex * 505 984-8800 x242