RetroZilla/extensions/transformiix/docs/compiled-stylesheets.html
2015-10-20 23:03:22 -04:00

255 lines
8.8 KiB
HTML

<html>
<head>
<title>Compiled Stylesheets</title>
<style>
.comment {
font-style: italic;
}
</style>
</head>
<body>
<h1>Compiled Stylesheets</h1>
<h2>Overview</h2>
<p>
There are 5 main entities: Stylesheet-loaders, stylesheet-compiler,
stylesheet, execution-state and processor. The normal usecase is:
<ol>
<li>Set up a stylesheet-loader to read a resource.
<li>Let it feed events to the stylesheet-compiler.
<li>The compiler creates a stylesheet.
<li>Init an execution-state with stylesheet, initial node, global
parameters and an outputhandler factory.
<li>Start the processor.
</ol>
</p>
<h2>Main classes</h2>
<h3>txStylesheet</h3>
<h4>Description:</h4>
<p>
This class represents a compiled stylesheet. If the stylesheet
contains imported and/or included stylesheets they are all compiled
into a single <code>txStylesheet</code>-object.
</p>
<p>
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 <code>txStylesheet</code> owns all objects
in the stylesheet, including the instructions in templates and
variables.
</p>
<p>
A single <code>txStylesheet</code>-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.
</p>
<h4>Typical functions:</h4>
<pre>
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();
</pre>
<h3>txStylesheetCompiler</h3>
<h4>Description:</h4>
<p>
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.
</p>
<p>
The output from the <code>txStylesheetCompiler</code> is a
ready-to-use <code>txStylesheet</code> object.
</p>
<p>
To load included and imported stylesheets the
<code>txStylesheetCompiler</code> calls the loader through a
<code>txIIncludeLoaderCallback</code> interface suppling the url to
load, and the <code>txStylesheetCompiler</code>-object that the loader
should use to notify its events to. There is a separate
<code>txStylesheetCompiler</code>-object for each sub-stylesheet,
however only the initial <code>txStylesheetCompiler</code> will create
a <code>txStylesheet</code>-object.
</p>
<p class="comment">
Do we want to refcount txIIncludeLoaderCallback? It might otherwise
be hairy to deal with loads being cancled or failing.
</p>
<h4>Typical functions:</h4>
<pre>
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);
</pre>
<h3>txHandlerTable</h3>
<h4>Description:</h4>
<p>
To process the elements and textnodes in the stylesheet the
<code>txStylesheetCompiler</code> calls different
stylesheet-compile-handlers. Which handler to call is decided by two
things:
<ol>
<li>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?
<li>The name and namespace of the element. (Of course, this doesn't
apply to textnodes).
</ol>
The handlers are global static C-style functions. The handlers
processes the elements and textnodes in the stylesheet and
creates instructions and toplevel-items.
</p>
<p>
To find which handler to call the compiler uses
<code>txHandlerTable</code>-objects. The <code>txHandlerTable</code>
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.
</p>
<p>
There are different <code>txHandlerTable</code>-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
<code>txStylesheetCompiler</code> always has a current
<code>txHandlerTable</code> which is used to find the handler to call.
</p>
<p>
The <code>txHandlerTable</code>s are initialized from static structs.
This is to avoid having large pieces of code containing very similar
code.
</p>
<h4>Typical functions:</h4>
<pre>
nsresult init(txHandlerTableData* aTableData);
txElementHandler* find(PRInt32 aNamespaceID, txAtom* aLocalName);
</pre>
<h3>txStylesheetCompilerState</h3>
<p class="comment">
Do we want to rename this txStylesheetCompilerInternal?
</p>
<h4>Description:</h4>
<p>
This class manages the internal state of the
<code>txStylesheetCompiler</code>. The reason that this is a separate
class is so that the <code>txStylesheetCompiler</code> can keep a clean
interface towards the stylesheet-loaders.
</p>
<p>
The <code>txStylesheetCompilerState</code>-class is used both by the
<code>txStylesheetCompiler</code>-class and by the
stylesheet-compile-handlers.
</p>
<p>
The class has three main purposes:
<ul>
<li>
Keep track of the current context. Such as:
<ul>
<li>Namespace mappings.
<li>Base-URI.
<li>Extension-element namespaces.
<li>Whitespace preservation mode.
</ul>
</li>
<li>
Store the state that the stylesheet-compile-handlers need. For
example the current xsl:for-each loop to add xsl:sort-elements to.
</li>
<li>
Keep track of the current <code>txHandlerTable</code>, so that the
right stylesheet-compile-handler is called for elements and text.
</li>
</ul>
</p>
<p>
This is the class that implements <code>txIParseContext</code> during
all stylesheet-compilation.
</p>
<h4>Typical functions:</h4>
<pre>
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);
</pre>
<h3>txExecutionState</h3>
<h4>Description:</h4>
<p>
This class manages all state during the execution of a stylesheet.
This includes
<ul>
<li>The current <code>txIEvalContext</code>.
<li>The next <code>txInstruction</code> to be executed.
<li>Variables that are in scope.
<li>Values of global variables and keys.
<li>Current result-handler.
<li>Stylesheet being executed.
</ul>
</p>
<p>
The <code>txExecutionState</code> 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.
</p>
<h4>Typical functions:</h4>
<pre>
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);
</pre>
<h3>txXSLTProcessor</h3>
<h4>Description:</h4>
<p>
This is a fully static class that contains the main loop for executing
a stylsheet.
</p>
<h4>Typical functions:</h4>
<pre>
nsresult execute(txExecutionState& aEs);
</pre>
</body>
</html>