gecko-dev/extensions/transformiix/docs/compiled-templates.html

274 строки
8.7 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<title>XSLT Templates and Compiling</title>
<style type="text/css">
.section {
background-color: #cfcfcf;
margin-left: 2em;
}
.required {
font-weight: bold;
}
.TODO {
color: red;
}
</style>
</head>
<body>
<h1>XSLT Templates and Compiling</h1>
<p>This document describes compiling of XSLT stylesheets and the
evaluation of the result.</p>
<div>
<ul>
<li><a href="#pre">Prerequisites</a></li>
<li><a href="#comp">Compilation</a></li>
<li><a href="#eval">Evaluation</a></li>
</ul>
</div>
<h2><a name="pre">Objectives:</a></h2>
<ul>
<li>Speed</li>
<li>Better support for AVTs</li>
<li>Interruptability of processing</li>
<li>exclude and alias namespaces</li>
</ul>
<h2>Concepts:</h2>
<div>
<dl>
<dt>LRE namespaces</dt>
<dd>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.</dd>
</dl>
</div>
<h2><a name="comp">Compilation:</a></h2>
<p>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.</p>
<div>The DOM nodes in a stylesheet get compiled into either
<ul>
<li>nothing :-) (stuff like xsl:output),</li>
<li><code>xslTopElement</code>s or</li>
<li><code>xslInstruction</code>s.</li>
</ul>
The <code>xslInstruction</code>s fall into classes,
<ol>
<li>simple instructions,</li>
<li>utilities (no-op, variable-pop, push-handler),</li>
<li>branching instructions,</li>
<li>instructions changing the result handler and</li>
<li>instructions calling into different
<code>xslTopElement</code>s.</li>
</ol>
</div>
<h2><a name="eval">How do instructions work?</a></h2>
<div>The general pattern used to create output from a set of
instructions is
<pre>while (instruction) {
rv = instruction.do(args);
if (NS_FAILED(rv)) {
//cleanup
return rv;
}
instruction = instruction.mNext;
}</pre>
This says pretty much all about simple and utility instructions.
</div>
<h3>Branching instructions</h3>
<div>see <a href="#choose">xsl:choose</a>. 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.</div>
<h3>Instructions that change the output handler</h3>
<div>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.</div>
<h3><a name="apply-imports">xsl:apply-imports</a></h3>
<div class="section">no idea</div>
<h3><a name="apply-templates">xsl:apply-templates</a></h3>
<div class="section">
<dl>
<dt>members:</dt>
<dd>
<dl>
<dt>select</dt> <dd>node-set-expression</dd>
<dt>mode</dt> <dd>qname</dd>
<dt>sorts</dt> <dd>list of xsl:sort elements</dd>
<dt>params</dt> <dd>list of xsl:with-param elements</dd>
</dl>
</dd>
<dt>do()</dt>
<dd>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?).</dd>
</dl>
</div>
<h3><a name="attribute">xsl:attribute</a></h3>
<div class="section">
<dl>
<dt>members:</dt>
<dd>
<dl>
<dt class="required">name</dt> <dd>AVT with QName value</dd>
<dt>namespace</dt> <dd>AVT with uri value</dd>
</dl>
</dd>
<dt>do()</dt>
<dd>the start tag pushes a textValueHandler, the end tag pops
the value handler and calls the outputhandler::attribute</dd>
</dl>
</div>
<h3><a name="attribute-set">xsl:attribute-set</a> (tle)</h3>
<div class="section"><span class="TODO">attribute sets are merged,
we should pay attention that multiple stylesheet compilers
don't mix their content. Order of attributes is relevant, IMHO.</span>
<dl>
<dt>members:</dt>
<dd>
<dl>
<dt class="required">name</dt> <dd>qname</dd>
<dt>use-attribute-sets</dt> <dd>list of qnames</dd>
</dl>
</dd>
<dt>do()</dt>
<dd>merging and stuff needed in the global stylesheet object,
(NOT part of <a href="#import-frame">import frame).</a></dd>
</dl>
</div>
<h3><a name="call-template">xsl:call-template</a></h3>
<div class="section">
<dl>
<dt>members:</dt>
<dd>
<dl>
<dt class="required">name</dt> <dd>qname</dd>
<dt>with-params</dt> <dd>list of xsl:with-params</dd>
</dl>
</dd>
<dt>do()</dt>
<dd>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.
<div class="issue">Can we cache this? What happens if a
added stylesheet between two transforms changes which
stylesheet this qname resolves to?</div></dd>
</dl>
</div>
<h3><a name="choose">xsl:choose</a></h3>
<div class="section">
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.
</div>
<h3><a name="comment">xsl:comment</a></h3>
<div class="section">
<dl>
<dt>do()</dt>
<dd>startElement pushes a textHandler, endElement takes the
value and calls ::comment() in the output handler</dd>
</dl>
</div>
<h3><a name="copy">xsl:copy</a></h3>
<div class="section">
<dl>
<dt>members:</dt>
<dd></dd>
<dt>do()</dt>
<dd>xsl:copy has a <a
href="#attribute-sets">use-attribute-sets</a> attribute,
<span class="TODO">TODO</span></dd>
</dl>
</div>
<h3><a name="copy-of">xsl:copy-of</a></h3>
<div class="section">
<dl>
<dt>members:</dt>
<dd>
<dl>
<dt class="required">select</dt>
<dd>an expression to be added to the result tree</dd>
</dl>
</dd>
<dt>do()</dt>
<dd>the value of the result is added to the result tree. If
the result is a RTF, the RTF is just fed into the output
handler, if the result is not a nodeset, it is converted
into a string and ::characters is called on the output
handler. For nodesets, the result is a list of source nodes
which have to be interpreted, for example thru the
stylesheet compiler. This has be xslt-blind, that is, xslt
elements in the source must be treated as LRE elements and
copied into the result, instead of generating XSLT
instructions. <span class="TODO">is this all?</span></dd>
</dl>
</div>
<h3><a name="decimal-format">xsl:decimal-format</a> (tle)</h3>
<div class="section">xsl:decimal-format is stored in the global
stylesheet object, import precedence <b>does not</b> apply.</div>
<h3><a name="element">xsl:element</a></h3>
<div class="section">
<dl>
<dt>members:</dt>
<dd>
<dl>
<dt class="required">name</dt> <dd>AVT with QName
value</dd>
<dt>namespace</dt> <dd>AVT with URI value</dd>
</dl>
</dd>
<dt>do()</dt>
<dd>xsl:element has <a
href="#attribute-sets">attribute-set</a>s, <span
class="TODO">todo</span>. Other than that, this just
generates an element. Note that the attributes of this
element have to be discarded, if the name AVT does not
evaluate to a QName.</dd>
</dl>
</div>
<h3><a name="fallback">xsl:fallback</a></h3>
<div class="section"><span class="TODO">do we care?</span></div>
<h3><a name=""></a></h3>
<div class="section">
<dl>
<dt>members:</dt>
<dd></dd>
<dt>do()</dt>
<dd></dd>
</dl>
</div>
</body>
</html>