Compiled Stylesheets

Overview

There are 5 main entities: Stylesheet-loaders, stylesheet-compiler, stylesheet, execution-state and processor. The normal usecase is:

  1. Set up a stylesheet-loader to read a resource.
  2. Let it feed events to the stylesheet-compiler.
  3. The compiler creates a stylesheet.
  4. Init an execution-state with stylesheet, initial node, global parameters and an outputhandler factory.
  5. Start the processor.

Main classes

txStylesheet

Description:

This class represents a compiled stylesheet. If the stylesheet contains imported and/or included stylesheets they are all compiled into a single txStylesheet-object.

The stylesheet contains functions for getting the different top-level entities that exist in a stylesheet, such as attribute-sets, templates and global variables. The txStylesheet owns all objects in the stylesheet, including the instructions in templates and variables.

A single txStylesheet-object can be used for multiple transformations, even running concurrently. Once a stylesheet is compiled it is never changed, nor does it carry any state.

Typical functions:

txInstruction* findTemplate(Node* aNode,
                            const txExpandedName& aMode,
                            txIMatchContext* aContext,
                            ImportFrame* aImportedBy,
                            ImportFrame** aImportFrame);
txDecimalFormat* getDecimalFormat(const txExpandedName& aName);
txInstruction* getAttributeSet(const txExpandedName& aName);
txOutputFormat* getOutputFormat();

txStylesheetCompiler

Description:

This class gets "events" from a stylesheet loader and creates a compiled stylesheet. The class calls back through a callback interface to the stylesheet-loader to load included and imported stylesheets.

The output from the txStylesheetCompiler is a ready-to-use txStylesheet object.

To load included and imported stylesheets the txStylesheetCompiler calls the loader through a txIIncludeLoaderCallback interface suppling the url to load, and the txStylesheetCompiler-object that the loader should use to notify its events to. There is a separate txStylesheetCompiler-object for each sub-stylesheet, however only the initial txStylesheetCompiler will create a txStylesheet-object.

Do we want to refcount txIIncludeLoaderCallback? It might otherwise be hairy to deal with loads being cancled or failing.

Typical functions:

nsresult startElement(PRInt32 aNamespaceID, txAtom* aLocalName,
                      txAtom* aPrefix, txStylesheetAttr* aAttributes,
                      PRInt32 aAttrCount);
nsresult endElement();
nsresult characters(const String& aStr);
nsresult doneLoading();
void cancel(nsresult aError);

txHandlerTable

Description:

To process the elements and textnodes in the stylesheet the txStylesheetCompiler calls different stylesheet-compile-handlers. Which handler to call is decided by two things:

  1. The "mode" of the compiler, i.e. is it processing a top-level element? Is it processing the contents of a template? Is it processing the children of a xsl:attribute-set element?
  2. The name and namespace of the element. (Of course, this doesn't apply to textnodes).
The handlers are global static C-style functions. The handlers processes the elements and textnodes in the stylesheet and creates instructions and toplevel-items.

To find which handler to call the compiler uses txHandlerTable-objects. The txHandlerTable contains a list of these stylesheet-compile-handlers keyed on element-name. It also contains a handler for text and a handler for LRE-elements.

There are different txHandlerTable-objects for different "modes" of the compiler. There is one for handling top-level elements, one for handling template-parameters, one for handling the contents of a xsl:attribte-set element, one for handling the contents of unsupported extension-elements etc. The txStylesheetCompiler always has a current txHandlerTable which is used to find the handler to call.

The txHandlerTables are initialized from static structs. This is to avoid having large pieces of code containing very similar code.

Typical functions:

nsresult init(txHandlerTableData* aTableData);
txElementHandler* find(PRInt32 aNamespaceID, txAtom* aLocalName);

txStylesheetCompilerState

Do we want to rename this txStylesheetCompilerInternal?

Description:

This class manages the internal state of the txStylesheetCompiler. The reason that this is a separate class is so that the txStylesheetCompiler can keep a clean interface towards the stylesheet-loaders.

The txStylesheetCompilerState-class is used both by the txStylesheetCompiler-class and by the stylesheet-compile-handlers.

The class has three main purposes:

This is the class that implements txIParseContext during all stylesheet-compilation.

Typical functions:

nsresult pushHandlerTable(txHandlerTable* aTable);
nsresult parsePattern(const String& aPattern, txPattern** aResult);
nsresult parseExpr(const String& aExpr, Expr** aResult);
nsresult addToplevelItem(txToplevelItem* aItem);
nsresult openInstructionContainer(txInstructionContainer* aContainer);
nsresult addInstruction(txInstruction* aInstruction);

txExecutionState

Description:

This class manages all state during the execution of a stylesheet. This includes

The txExecutionState also acts as a general-purpose stack that instructions can use to communicate between each other. The class is the owner of this data and will delete it as appropriate if the execution aborts.

Typical functions:

nsresult pushEvalContext(txIEvalContext* aContext);
txIEvalContext* popEvalContext();
nsresult pushString(const nsAString& aStr);
void popString(nsAString& aStr);
txInstruction* getNextInstruction();
nsresult runTemplate(txInstruction* aInstruction);
void gotoInstruction(txInstruction* aNext);

txXSLTProcessor

Description:

This is a fully static class that contains the main loop for executing a stylsheet.

Typical functions:

nsresult execute(txExecutionState& aEs);