Subject: Re: [xsl] Re: Assignment no, dynamic scoping si (was: Re: RE: Wishes for XSL revisions ... From: Gunther Schadow <gunther@xxxxxxxxxxxxxxxxxxxxxx> Date: Wed, 02 Jan 2002 11:49:41 -0500 |
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:
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: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>
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: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>
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.
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@xxxxxxxxxxxxxxx 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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Re: Assignment no, dynamic sc, Dimitre Novatchev | Thread | Re: [xsl] Re: Assignment no, dynami, Wendell Piez |
[xsl] Re: copying <xsl:stylesheet> , Dimitre Novatchev | Date | [xsl] Re:, Elliotte Rusty Harol |
Month |