# 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 `txHandlerTable`s 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:

- Keep track of the current context. Such as:
  - Namespace mappings.
  - Base-URI.
  - Extension-element namespaces.
  - Whitespace preservation mode.
- Store the state that the stylesheet-compile-handlers need. For example the current xsl:for-each loop to add xsl:sort-elements to.
- Keep track of the current `txHandlerTable`, so that the right stylesheet-compile-handler is called for elements and text.

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 current `txIEvalContext`.
- The next `txInstruction` to be executed.
- Variables that are in scope.
- Values of global variables and keys.
- Current result-handler.
- Stylesheet being executed.

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);