This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Attributes, modes and templates [solution]


Just to belatedly close out this thread, I have a response to David,
and a final solution to my problem which I hope will help others
(especially DocBookers using XSL).

AL> <variablelist> <!-- element content --> </variablelist>

AL> would be treated as per Norm's stylesheets. but the XML element
AL> with the `role' atttribute set like so:

AL> <variablelist role="programmers"> <!-- element content -->
AL> </variablelist>

AL> would be treated as per my special customizations,

>>>>> "DC" == David Carlisle <davidc@nag.co.uk> writes:

DC> well doesn't that just mean that your top level sheet needs a

DC> <xsl:template match="variablelist[@role='programmers']"> do
DC> something different, </xsl:template>

Unfortunately not, because as I attempted to explain earlier in the
thread, I would then be responsible for implementing all the potential
subelements either explicitly (via for-each type constructs) or
implicitly (via modes) [the key here is that I'm *customizing* stock
stylesheets I want to mininize my customizations to the bare minimum,
and only in some cases do I want to do something different)].  I don't
want to have to treat those subelements with the attribute like:

<variablelist>
 <varlistentry>
   <term><corpauthor role="programmer-info">Blah</corpauthor></term>
   <listitem role="programmer-info"><para>Some text</para></listitem>
 </varlistitem>
</variablelist>

I want to be able to specify only the top level, like so:

<variablelist role="programmer-info">
 <varlistentry>
   <term><corpauthor>Blah</corpauthor></term>
   <listitem><para>Some text</para></listitem>
 </varlistitem>
</variablelist>

i.e. without having to write a procedural-style parsing inside the
template match you mentioned above, for the subelements like term or
varlistentry, since the content model allows so many different
variants that I would essentially have to reimplement the stock
stylesheet for the variablelist element and all of it's potential
children.

I then thought about using modes, but as Wendell correctly identified,
once in a mode in XSL, that's where you stay, unless a further
template explicitly takes you out of it (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> Actually, I started this thread, with such a concrete example:

DC> perhaps but I'm not going to look at it at this time of night
DC> (even if I am only watching the election results....:-)

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))))

I didn't see an example quite like this in the FAQ, so it might make a
good new entry, since I'm sure it's likely to trip up those folks
trying to customize complex or modular stylesheets (such as Norm's
DocBook XSL stylesheets: the `role' attribute is provided specifically
for user customization on each DocBook element).

Now, I'm sure that someone better schooled in XSL than I is going to
say, "well if *that's* what you wanted to do, then why didn't you tell
us first up, I could have told you *that*", but sometimes half the
solution is stating the problem in the right kind of way so that those
more experienced can "match" the problem with the right solution
template, as it were.  ;-) The other half, is having folks who
carefully notice *where* and *how* the problem differs from simpler
and more obvious problems that are similar, but differ in a seemingly
minor, but crucial respect.

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.  My thanks both to Wendell for pointing this out and to
David Carlisle for helping me clarify the problem.
  
I hope this belated followup helps others on the same migration path.

Alex
-- 
Alex Lancaster * alex@santafe.edu * www.santafe.edu/~alex * 505 984-8800 x242
Santa Fe Institute (www.santafe.edu) & Swarm Development Group (www.swarm.org)


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]