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]
Other format: [Raw text]

Re: Re: Assignment no, dynamic scoping si (was: Re: RE: Wishes for XSL revisions ...


Dimitre,

thank you so much for your response to the use case. I hear
you, I listen to what you say, I always do. And if you can
in fact show that nothing else is needed, I'll be happy to
accept that. Noone wants needless features :-)

>>Say you have a stylesheet "book.xsl" containing templates to process
>>the various element types in a book (e.g. book, chapter, paragraph,
>>...) where each template applies templates recursively, like this:
>>
>><xsl:template match="chapter">
>>  <fo:block>
>>    <xsl:apply-templates/>
>>  </fo:block>
>></xsl:template>
>>
>>Consider the case that you need to make a stylesheet that imports a
>>third party "book.xsl" then overrides its templates for 'book' and
>>'paragraph' elements with custom processing but with a minimum of
>>duplication. For some reason, you would like to pass a parameter from
>>the 'book' template to the 'paragraph' template.
>>
>>Unfortunately, today this requires that you duplicate and modify the
>>'chapter' template (and possibly others) from the "book.xsl"
>>stylesheet to pass along the parameter. You end up with a stylesheet
>>that contains most or all of the imported stylesheet.
> 
> Duplicating and modifying the 'chapter' template (and possibly others) 

> ***is not required***.
> 
> Just declare a global variable and access it in the 'paragraph' template.



I must be missing what you are saying or you must be missing a
critical point of the use case. With a global variable you have
one fixed, constant, immutable object, available throughout all
the style sheet under the name of that variable. That doesn't
allow you to dynamically change a property (e.g., text-color)
in one template T1 and then make that binding available in another
template Tn without rewriting the entire possible call chain from
T1 to Tn.


> One may argue that within the 'book' template the necessary value 

> can be obtained "dynamically", while the value of a global variable 

> is "static". This is clearly not true, as any variable (global included) 

> can have templates instantiated/called within its body in order to

> define its value.


But in a global variable you call these templates somewhere when
the style sheet is first loaded, not at the point when the input
document's element is processed that is supposed to change
text-color from black to red.


>>With support for dynamic scope, the 'book' template would be able to
>>bind variables that are visible for the 'paragraph' template without
>>requiring modifications of other templates in "book.xsl".


Visible yes, dynamically updateable, no. Now don't start the
assignment issue again. Noone is asking for assignment and
everyone should understand that a side-effected global variable
is just about the worst programming language construct possible
(even before goto.)

I don't see how a global variable can do what it should in this
use case. But I value your opinion and insight enough that I
give you a more detailed scenario so you can make your point
clearer:

USE CASE (EXPANDED)

The following is the stylesheet from a third party called
bigbucksbooks.com. Bigbucksbooks.com is so popular in the
industry that everybody uses their stuff. Competitors have
frequently tried to produce similar if not better style
sheets, but Bigbucksbooks changes theirs all the time, adding
feature after feature and the whole world happily goes with
them whatever they do.

<xsl:stylesheet id='urn:bigbucksbooks.com:onlinebook'>

<xsl:output method='html'/>

<xsl:template match='book'>
   ...
   <xsl:apply-templates/>
   ...
</xsl:template>

<xsl:template match='part'>
   ...
   <xsl:apply-templates/>
   ...
</xsl:template>

<xsl:template match='chapter'>
   ...
   <xsl:apply-templates/>
   ...
</xsl:template>

<xsl:template match='section'>
   ...
   <xsl:apply-templates/>
   ...
</xsl:template>

<xsl:template match='table'>
   ...
   <xsl:apply-templates/>
   ...
</xsl:template>

<xsl:template match='tablecell'>
   ...
   <xsl:apply-templates/>
   ...
</xsl:template>

<xsl:template match='list'>
   ...
   <xsl:apply-templates/>
   ...
</xsl:template>

<xsl:template match='listitem'>
   ...
   <xsl:apply-templates/>
   ...
</xsl:template>

<xsl:template match='paragraph'>
   <p>
     <xsl:apply-templates/>
   </p>
</xsl:template>

</xsl:stylesheet>

For brevity I show an EBNF of the book schema:

content   := (paragraph|table|list)*
book      := (content|part|chapter|section)*
part      := (content|chapter|section)*
chapter   := (content|section)*
section   := content*
table     := tablecell*
list      := listitem*
tablecell := paragraph*
listitem  := paragraph*

The point being that there are very many paths to go from
a section to a paragraph, for example:

book -> ... -> section -> paragraph
book -> ... -> section -> table -> tablecell -> paragraph
book -> ... -> section -> list -> listitem -> paragraph

And because bigbucksbooks adds new features all the time,
such as frame, box, float, imagetitle, rotated-text, ...
all of them eventually have paragraphs nested within
them, the various possible paths from a section to a
paragraph are always more, and more.


Now here is a one-man's shop, lowlyweb.org, that has must use
bigbucksbook's stylesheet because his own customers demand it.
On the other hand, he also needs some extension to bigbucksbooks
stylesheet, because the business niche lowlyweb.com works in
is so insignificant that bigbucksbooks just doesn't see their
needs as anything worthy of bothering with.

Let's say for the example that bigbucksbooks online-book
stylesheet does not allow anyone to define customized CSS
classes to the HTML elements. But lowlyweb works with a
customer that produces commentated textcritical corpora of
the Buddhist canon and early secondary literature. For
that they need to distinguish for each part of the text what
its source is, and they want to use color to show the source.
Every section represents one source in their world. On the
other hand, for reasons of the HTML CSS stylesheet, they need
the CSS class to be attached to every paragraph element in
the output.

So, in a world with dynamic scoping / implicit parameters,
lowlyweb.org would do this:

<xsl:stylesheet id='urn:lowlyweb.org:onlinebook'>

<xsl:import href='http://bigbucksbooks.com/onlinebook.xsl'/>

<xsl:template match='section'>
   ...
   <xsl:apply-templates>
     <xsl:with-implicit-param name='source' select='@source'/>
   </xsl:apply-templates>
   ...
</xsl:template>

<xsl:template match='paragraph'>
   <xsl:implicit-param name='source' select='@source'/>
   <p class='$source'>
     <xsl:apply-templates/>
   </p>
</xsl:template>

</xsl:stylesheet>

This template would only touch the section and paragraph elements
of bigbucksbooks and would leave everything else untouched.
The implicit parameter source is bound to the @source value given
in the document for everything nested within that section. Now,
most of this stuff doesn't care, until we get down to the paragraph
element that now has this implicit parameter available no matter
how many things were passed through.

I cannot see how to do that with global variables as you suggest,
because that book contains many sections and needs to switch
between the different sources all the time per each section.

I can see how one can do the same thing with explicit parameters,
which however, requires modifying all of bigbucksbooks templates
for table, list (and then: frame, box, float, imagetitle,
rotated-text, ...).

So, if you could show me how this can be done without changing the
whole thing, I am all ears.

You also note:

> Another disadvantage of dynamic-scoped variables is that separating 

> and making remote the definition of a parameter/variable from its 

> reference/use may present difficulties to its type-checking.
> 
> Also, any such separation/remoting makes the code more difficult to 

> understand and maintain.


I definitely agree with you that these are concerns with
simple dynamically scoped variables. When examining just
one lexical scope, they appear as free variables and one
doesn't know what they are.

In my proposal (submitted under Request for ...) and in this
example, however, you see that implicit parameters are
declared just as explicit parameters in their lexical
scope. So you know exactly what they are (of course their
actual binding will be dynamic.)

If there were any type checking with XSLT (say, if XSLT were
a strongly typed language) the type would be mentioned in
the declaration everywhere and could be validated throughout
the stylesheet at compile-time. So it's safe.

Eager to hear your careful response,
-Gunther



-- 
Gunther Schadow, M.D., Ph.D.                    gschadow@regenstrief.org
Medical Information Scientist      Regenstrief Institute for Health Care
Adjunct Assistant Professor        Indiana University School of Medicine
tel:1(317)630-7960                         http://aurora.regenstrief.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]