A stylesheet is a set of rules for transformation of XML. The stylesheet syntax allows one to intermix a sequence of xml-micro's, xml-macro's, and top-level Scheme expressions.
The grammar for
stylesheet is given below:
stylesheet-form ::= (stylesheet body-item*) body-item ::= xml-micro-form | xml-macro-form | top-level-sceheme-expression
A stylesheet form evaluates to a stylesheet object.
The semantics of top-level definitions within a stylesheet is identical to that of PLT Scheme's units.
An xml-micro performs a single transformation of its argument. The result of this transformation is not further "expanded".
The grammar for
micro-form ::= (xml-micro trigger-tag expression) trigger-tag ::= element-tag | *text* | *data*
The expression in an xml-micro must evaluate to a function of which takes an XML node as its argument, and (generally) returns a node or nodeset.
An xml-macro performs a transformation of its argument; the result of this transformation further "expanded" until no further transformations are possible.
The grammar for
macro-form ::= (xml-macro trigger-tag expression) trigger-tag ::= element-tag | *text* | *data*
The expression in an xml-macro must evaluate to a function of which takes an XML node as its argument, and returns a node or nodeset.
No further transformations of a node are possible when no more xml-micros or xml-macros are triggered by that node under the stylesheet being applied.
stylesheet->expander :: stylesheet -> (function node -> node))
This function converts a stylesheet to an expander function. The return-result may be applied to an XML node to apply the stylesheet's transformations.
This form is used to combine multiple stylesheets. The result of evaluating a compound-stylesheet is a new stylesheet object.
The grammar for a
compound-stylesheet is given below:
compound-ss-form ::= (compound-stylesheet expression+)
Each expression must evaluate to a stylesheet object.
The example below is a complete working stylesheet which translates a collection of poetry into HTML. The 'micro' for the poem element formats a poem into HTML. The 'macro' for the book element creates a skeletal HTML document, with a new contents element which contains both a table of contents element and the poems to be formatted. The 'micro' for the contents element formats the table of contents and uses
xml-expand to invoke the expander on each of the poems.
poetry->html is bound to the result of applying
stylesheet->expander to the stylesheet, producing a function which takes a single argument: the poetry book element.
(define poetry->html (stylesheet->expander (stylesheet (define-element toc) (define-element contents) (xml-micro poem (lambda (x) (xml-match x [(poem title: ,t poet: ,a tag: ,m (stanza (line ,l1) (line ,l) ...) ...) (h4:div (h4:p) (h4:a h4:name: m) (h4:strong t) (h4:br) (h4:em a) (list (h4:p) l1 (list (h4:br) l) ...) ...)]))) (xml-micro contents (lambda (x) (xml-match x [(contents (toc (poem title: ,t poet: ,a tag: ,m . ,rest) ...) ,p* ...) (h4:div (h4:p) "Table of Contents:" (h4:ul (h4:li (h4:a h4:href: (string-append "#" m) t)) ...) (xml-expand p*) ...)]))) (xml-macro book (lambda (x) (xml-match x [(book title: ,bt ,p* ...) (h4:html (h4:head (h4:title bt)) (h4:body (h4:h1 bt) (contents (toc p* ...) p* ...)))]))) )))