XSLT Templates and Compiling
This document describes compiling of XSLT stylesheets and the
evaluation of the result.
- Speed
- Better support for AVTs
- Interruptability of processing
- exclude and alias namespaces
Concepts:
- LRE namespaces
- All namespace aliases are merged wit import precedence
into an array of all namespace ids, which is used to map the
LRE namespace in the source to the LRE namespace in the
result. Non-aliased namespaces just have their namespace id
in that array.
The XSLT specification describes XSLT in terms of the XPath
datamodel, something pretty close to a DOM. So we talk about the
input in terms of DOM elements.
The DOM nodes in a stylesheet get compiled into either
- nothing :-) (stuff like xsl:output),
xslTopElement
s or
xslInstruction
s.
The
xslInstruction
s fall into classes,
- simple instructions,
- utilities (no-op, variable-pop, push-handler),
- branching instructions,
- instructions changing the result handler and
- instructions calling into different
xslTopElement
s.
The general pattern used to create output from a set of
instructions is
while (instruction) {
rv = instruction.do(args);
if (NS_FAILED(rv)) {
//cleanup
return rv;
}
instruction = instruction.mNext;
}
This says pretty much all about simple and utility instructions.
Branching instructions
see
xsl:choose. The trailing single
no-op helps in rejoining the paths, as that no-op can be created
before the paths and thus easily appended to each end of the
paths.
Instructions that change the output handler
These instructions (attribute, comment, pi creating text
handlers, variable possibly creating a rtf handler) get created
by inserting a push-handler-instruction into the workflow for
the start of the element and the XSLT instruction at the
end. The handler instruction should keep a non-owning reference
to the push-handler-instruction to get the result and restore
the previous handler.
no idea
- members:
-
- select
- node-set-expression
- mode
- qname
- sorts
- list of xsl:sort elements
- params
- list of xsl:with-param elements
- do()
- set up the params, if any, evaluate the select, create a
evalContext and push it on the evalContextStack. push the next
instruction to the instruction return stack. trigger the new
context (how do we do this?).
- members:
-
- name
- AVT with QName value
- namespace
- AVT with uri value
- do()
- the start tag pushes a textValueHandler, the end tag pops
the value handler and calls the outputhandler::attribute
- members:
-
- name
- qname
- use-attribute-sets
- list of qnames
- do()
- part of import frame
- members:
-
- name
- qname
- with-params
- list of xsl:with-params
- do()
- push the next instruction onto the instruction return
stack, lookup the template and set the instruction pointer
to the called template. Setup the params, if there are. This
does not change the evalContextStack.
Can we cache this? What happens if a
added stylesheet between two transforms changes which
stylesheet this qname resolves to?
This is a branching instruction with one exit point and several
conditional entry points (xsl:when) and one default
(xsl:otherwise). The conditional entry points start with a
conditionalGotoInstrunction, which jumps to the next entry point
if they don't succeed. Each of them ends with a gotoInstruction
that jumps to the end of the xsl:choose (for simplicity in the
compilation phase, this might be a noopInstruction). The
xsl:otherwise is just the instructions list of the
xsl:otherwise, linked to the ending noopInstruction. Note that
this construct a single instruction list for the complete
xsl:choose, as the mNext of the final gotos is the next entry
point. This mNext is only used for iterations, though.
- do()
- startElement pushes a textHandler, endElement takes the
value and calls ::comment() in the output handler