You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mo...@apache.org on 2001/12/14 14:09:57 UTC
cvs commit: xml-xalan/java/xdocs/sources/xsltc ast_stage1.gif ast_stage2.gif ast_stage3.gif class_loader.gif compiler_design.gif output_settings.gif overall_design.gif runtime_design.gif translet_wrapping.gif trax_output_settings.gif trax_translet_wrapping.gif uri_resolver.gif xsltc_overview.xml index.xml xsltc_compiler.xml xsltc_runtime.xml xsltc_trax.xml
morten 01/12/14 05:09:57
Modified: java/xdocs/sources/xsltc index.xml xsltc_compiler.xml
xsltc_runtime.xml xsltc_trax.xml
Added: java/xdocs/sources/xsltc ast_stage1.gif ast_stage2.gif
ast_stage3.gif class_loader.gif compiler_design.gif
output_settings.gif overall_design.gif
runtime_design.gif translet_wrapping.gif
trax_output_settings.gif trax_translet_wrapping.gif
uri_resolver.gif xsltc_overview.xml
Log:
Update of the XSLTC design documents
PR: none
Obtained from: n/a
Submitted by: morten@xml.apache.org
Reviewed by: morten@xml.apache.org
Revision Changes Path
1.4 +162 -58 xml-xalan/java/xdocs/sources/xsltc/index.xml
Index: index.xml
===================================================================
RCS file: /home/cvs/xml-xalan/java/xdocs/sources/xsltc/index.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- index.xml 2001/05/14 16:07:28 1.3
+++ index.xml 2001/12/14 13:09:56 1.4
@@ -56,63 +56,167 @@
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
-->
-<s1 title="Introduction to XSLTC">
- <p><ref>Design documents by <jump href="mailto:morten@xml.apache.org">Morten Jørgensen</jump>
- - updated 06.03.2001</ref></p>
-<ul>
- <li><link anchor="compiler">Compiler design</link></li>
- <li><link anchor="runtime">Runtime library/DOM design</link></li>
- <li><link idref="xsltc_trax">Integration of the Translet API and TrAX</link> (by G Todd Miller)</li>
-
-</ul>
-<p>See also <jump href="../xsltc_usage.html">Using XSLTC</jump>.</p>
-<anchor name="compiler"/>
- <s2 title="Compiler design">
- <p><link idref="xsltc_compiler"><img src="compiler_architecture.gif" alt="compiler_architecture.gif"/></link></p>
- <p><ref>Figure 1: Compiler architecture overview</ref></p>
- <p>Click on the picture to jump to the overall design document for the compiler.</p>
- <p>Each XSL element/function and XPath expression/pattern is represented by
- its own class in the Abstract Syntax Tree (AST). Some of these classes have
- their own design documents (I am working on the rest of them):</p>
- <s3 title="XSL elements">
- <ul>
- <li>
- <link idref="xsl_whitespace_design"><xsl:preserve-space>/<xsl:strip-space></link>
- </li>
- <li>
- <link idref="xsl_sort_design"><xsl:sort></link>
- </li>
- <li>
- <link idref="xsl_key_design"><xsl:key></link>
- </li>
- <li>
- <link idref="xsl_comment_design"><xsl:comment>/<xsl:message></link>
- </li>
- </ul>
- </s3>
- <s3 title="XSL functions">
- <ul>
- <li>
- <link idref="xsl_key_design">key()</link>
- </li>
- <li>
- <link idref="xsl_lang_design">lang()</link>
- </li>
- <li>
- <link idref="xsl_unparsed_design">unparsed-entity-uri()</link>
- </li>
- </ul>
- </s3>
- </s2><anchor name="runtime"/>
- <s2 title="Runtime library/DOM design">
- <p><link idref="xsltc_runtime"><img src="runtime_architecture.gif" alt="runtime_architecture.gif"/></link></p>
- <p><ref>Figure 2: Runtime library architecture overview</ref></p>
- <p>Click on the picture to jump to the overall design document for the XSLTC
- runtime library. This document describes the structure of the compiled
- translet as well as the translet runtime library.</p>
- <p>The <link idref="xsltc_dom">Internal DOM</link> describes the components and structure of the internal DOM,
- support for DOM2 navigation, the DOM adapter, DOM multiplexer, and DOM builder.</p>
- <p><link idref="xsltc_namespace">Namespaces</link> explains how XSLTC (including the compiler) handles
- namespaces.</p>
+
+<s1 title="XSLTC Documentation">
+
+ <s2 title="XSLTC User Documentation">
+
+ <p>The following user documentation is currently available:</p>
+
+ <ul>
+ <li><link idref="README">XSLTC Installation and Requirements 'README'</link></li>
+ <li><link anchor="user_cmdline">Command-line user document</link></li>
+ <li><link anchor="user_native">XSLTC Native API reference</link></li>
+ <li><link anchor="user_trax">XSLTC TrAX API reference</link></li>
+ <li><link anchor="user_perf">XSLTC Performance Hints</link></li>
+ </ul>
</s2>
+
+ <s2 title="XSLTC Design Documents">
+
+ <p>The following design documents are currently available:</p>
+
+ <ul>
+ <li><link anchor="overall">XSLTC overall design</link></li>
+ <li><link anchor="compiler">XSLTC compiler design</link></li>
+ <li><link anchor="runtime">XSLTC runtime library design</link></li>
+ <li><link anchor="dom">XSLTC internal DOM design</link></li>
+ <li><link anchor="trax">XSLTC TrAX implementation design</link></li>
+ </ul>
+
+
+ <!--========================= OVERALL DESIGN ==========================-->
+ <anchor name="overall"/>
+ <s3 title="XSLTC overall design">
+
+ <p>The figure below describes the overall design of XSLTC's compiler:</p>
+ <p><img src="overall_design.gif" alt="overall_design.gif"/></p>
+ <p><ref>Figure 1: Architectural overview of XSLTC</ref></p>
+
+ <p>A client application can use XSLTC either through its
+ <link anchor="user_native">native API</link> or through or implementation
+ of the <link anchor="user_trax">TrAX API</link>. The
+ <link anchor="compiler">compiler</link> generates one or more Java classes
+ (we have chosen to call them 'translets').
+ The <link anchor="runtime">runtime library</link> contains classes that
+ can load these translets and use them to transform XML documents to some
+ markup language or plain text. There is also a detailed document describing
+ <link idref="xsltc_namespace">namespace handling</link> in all parts of
+ XSLTC (compiler, internal DOM, and output handler).</p>
+
+ </s3>
+
+ <!--========================= COMPILER DESIGN =========================-->
+ <anchor name="compiler"/>
+ <s3 title="XSLTC compiler design">
+
+ <p>The figure below describes the overall design of XSLTC's compiler:</p>
+ <p><img src="compiler_design.gif" alt="compiler_design.gif"/></p>
+ <p><ref>Figure 2: Compiler architecture overview</ref></p>
+
+ <p>There is also a <link idref="xsltc_compiler">high-level design</link>
+ document for XSLTC's compiler. Apart from that you can also find separate
+ design documents for some XSL elements and XPath expressions, patterns
+ and functions:</p>
+
+ <table width="90%">
+ <tr>
+ <td>
+
+ <s4 title="XSL elements">
+ <ul>
+ <li><link idref="xsl_sort_design"><xsl:sort></link></li>
+ <li><link idref="xsl_key_design"><xsl:key></link></li>
+ <li>
+ <link idref="xsl_whitespace_design"><xsl:preserve-space>/<xsl:strip-space></link>
+ </li>
+ <li>
+ <link idref="xsl_comment_design"><xsl:comment>/<xsl:message></link>
+ </li>
+ </ul>
+ </s4>
+
+ </td><td>
+
+ <s4 title="XPath functions">
+ <ul>
+ <li><link idref="xsl_key_design">key()</link></li>
+ <li><link idref="xsl_lang_design">lang()</link></li>
+ <li><link idref="xsl_unparsed_design">unparsed-entity-uri()</link></li>
+ </ul>
+ </s4>
+
+ </td></tr>
+ <tr><td>
+
+ <s4 title="XPath expressons">
+ <ul>
+ <li>Step</li>
+ </ul>
+ </s4>
+
+ </td><td>
+
+ <s4 title="XPath patterns">
+ <ul>
+ <li>StepPattern</li>
+ </ul>
+ </s4>
+
+ </td></tr>
+ </table>
+
+ </s3>
+
+ <!--========================= RUNTIME DESIGN ==========================-->
+ <anchor name="runtime"/>
+ <s3 title="XSLTC runtime library design">
+
+ <p>The runtime portion of XSLTC has four main components; the internal DOM
+ implementation (<u>not</u> W3C), the translet class(es), the runtime
+ library and the output processor:</p>
+
+ <p><img src="runtime_design.gif" alt="runtime_design.gif"/></p>
+ <p><ref>Figure 3: Runtime library architecture overview</ref></p>
+
+ <p>The <link idref="xsltc_runtime">runtime library design</link> document
+ describes the structure of the compiled translet as well as the translet
+ runtime library.</p>
+
+ <p>The <link idref="xsltc_dom">Internal DOM design</link> document
+ describes the components and structure of the internal DOM, support for
+ DOM2 navigation, the DOM adapter, DOM multiplexer, and DOM builder.</p>
+
+ <p>The <link idref="xsltc_iterator">iterator design</link> document
+ describes the general design of the internal DOM iterators and describes
+ some of the more complicated iterators in detail.</p>
+
+ </s3>
+
+ <!--========================== TRAX DESIGN ===========================-->
+ <anchor name="trax"/>
+ <s3 title="XSLTC TrAX Implementation">
+
+ <p>An implementation of the JAXP/ TrAX interface was added on to XSLTC
+ at a late stage. Special care was taken to preserve the small footprint
+ and high performance of XSLTC. The following design was used to wrap
+ XSLTC behind a lightweight (but complete) TrAX implementation:</p>
+
+ <p><img src="trax_translet_wrapping.gif" alt="trax_translet_wrapping.gif"/></p>
+ <p><ref>Figure 4: XSLTC TrAX interface implementation</ref></p>
+
+ <p>The <link idref="xsltc_trax">TrAX design</link> document contains
+ details of XSLTC's TrAX implementation.</p>
+
+ <p>XSLTC also has a 'smart' TrAX <code>TransformerFactory</code> class
+ that will alternate between using XSLTC and Xalan for transformations.
+ This factory class will make its choices based on usage patterns. This will
+ be described in a separate design document.</p>
+
+ </s3>
+
+ </s2>
+
+ <p><ref>Design documents by <jump href="mailto:morten@xml.apache.org">Morten Jørgensen</jump> - updated 13.12.2001</ref></p>
+
</s1>
1.3 +263 -152 xml-xalan/java/xdocs/sources/xsltc/xsltc_compiler.xml
Index: xsltc_compiler.xml
===================================================================
RCS file: /home/cvs/xml-xalan/java/xdocs/sources/xsltc/xsltc_compiler.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- xsltc_compiler.xml 2001/05/14 16:07:32 1.2
+++ xsltc_compiler.xml 2001/12/14 13:09:56 1.3
@@ -56,54 +56,100 @@
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
-->
- <s1 title="XSLTC Compiler Design">
- <ul>
- <li><link anchor="overview">Compiler Overview</link></li>
- <li><link anchor="ast">Building an Abstract Syntax Tree</link></li>
- <li><link anchor="typecheck">Type-check and Cast Expressions</link></li>
- <li><link anchor="compile">Code generation</link></li>
+
+<s1 title="XSLTC Compiler Design">
+ <ul>
+ <li><link anchor="overview">Compiler Overview</link></li>
+ <li><link anchor="ast">Building the Abstract Syntax Tree</link></li>
+ <li><link anchor="typecheck">Type-check and Cast Expressions</link></li>
+ <li><link anchor="compile">JVM byte-code generation</link></li>
+ </ul>
+
+ <!--=================== OVERVIEW SECTION ===========================-->
+
+ <anchor name="overview"/>
+ <s2 title="Compiler overview">
+
+ <p>The main component of the XSLTC compiler is the class</p>
+ <ul>
+ <li><code>org.apache.xalan.xsltc.compiler.XSLTC</code></li>
</ul>
- <anchor name="overview"/>
- <s2 title="Compiler overview">
+ <p>This class uses three parsers to consume the input stylesheet(s):</p>
- <p>The input stylesheet is parsed using the SAX 1-based parser from Sun's
- Project X:</p>
<ul>
- <li><code>com.sun.xml.parser.Parser</code></li>
+ <li><code>javax.xml.parsers.SAXParser</code></li>
</ul>
+
+ <p>is used to parse the stylesheet document and pass its contents to
+ the compiler as basic SAX2 events.</p>
- <p>This parser builds a DOM from the stylesheet document, and hands this
- DOM over to the compiler. The compiler uses its own specialised parser to
- parse XPath expressions and patterns:</p>
<ul>
<li><code>com.sun.xslt.compiler.XPathParser</code></li>
</ul>
- <p>Both parsers are encapsulated in XSLTC's parser class:</p>
+
+ <p> is a parser used to parse XPath expressions and patterns. This parser
+ is generated using JavaCUP and JavaLEX from Princeton University.</p>
+
<ul>
<li><code>com.sun.xslt.compiler.Parser</code></li>
</ul>
+
+ <p>is a wrapper for the other two parsers. This parser is responsible for
+ using the other two parsers to build the compiler's abstract syntax tree
+ (which is described in more detail in the next section of this document).
+ </p>
+
+ </s2>
- </s2><anchor name="ast"/>
- <s2 title="Building an Abstract Syntax Tree">
+ <!--============== ABSTRACT SYNTAX TREE SECTION ======================-->
+ <anchor name="ast"/>
+ <s2 title="Building an Abstract Syntax Tree">
+
+ <p>An abstract syntax tree (AST) is a data-structure commonly used by
+ compilers to separate the parse-phase from the later phases of the
+ compilation. The AST has one node for each parsed token from the stylesheet
+ and can easily be parsed at the stages of type-checking and bytecode
+ generation.</p>
+
<ul>
- <li><link anchor="mapping">Mapping stylesheet elements to Java classes</link></li>
- <li><link anchor="domxsl">Building a DOM tree from the input XSL file</link></li>
+ <li>
+ <link anchor="mapping">Mapping stylesheet elements to AST nodes</link>
+ </li>
+ <li>
+ <link anchor="domxsl">Building the AST from AST nodes</link>
+ </li>
+ <li>
+ <link anchor="mapping">Mapping XPath expressions and patterns to additional AST nodes</link>
+ </li>
</ul>
- <p>The SAX parser builds a standard W3C DOM from the source stylesheet.
- This DOM does not contain all the information needed to represent the
- whole stylesheet. ( Remember that XSL is two languages; XML and XPath.
- The DOM only covers XML. ) The compiler uses the DOM to build an
- abstract syntax tree (AST) that contains all the nodes from the DOM, plus
- additional nodes for the XPath expressions.</p>
+
+ <p>The SAX parser passes the contents of the stylesheet to XSLTC's main
+ parser. The SAX events represent a decomposition of the XML document that
+ contains the stylesheet. The main parser needs to create one AST node from
+ each node that it receives from the SAX parser. It also needs to use the
+ XPath parser to decompose attributes that contain XPath expressions and
+ patterns. Remember that XSLT is in effect two languages: XML and XPath,
+ and one parser is needed for each of these languages. The SAX parser breaks
+ down the stylesheet document, the XPath parser breaks down XPath expressions
+ and patterns, and the main parser maps the decomposed elements into nodes
+ in the abstract syntax tree.</p>
+
<anchor name="mapping"/>
- <s3 title="Mapping stylesheets elements to Java classes">
- <p>Each XSL element is represented by a class in the
- <code>com.sun.xslt.compiler</code> package. The Parser class contains a
- Hashtable that that maps XSL instructions to classes that inherit from a
- common parent class 'Instruction' (which again inherits from
- 'SyntaxTreeNode'). This mapping is set up in the <code>initClasses()</code> method:</p>
-<source> private void initStdClasses() {
+ <s3 title="Mapping stylesheets elements to AST nodes">
+
+ <p>Every element that is defined in the XSLT 1.0 spec is represented by a
+ a class in the <code>org.apache.xalan.xsltc.compiler</code> package. The
+ main parser class contains a <code>Hashtable</code> that that maps XSL
+ elements into Java classes that make up the nodes in the AST. These Java
+ classes all reside in the <code>org.apache.xalan.xsltc.compiler</code>
+ package and extend either the <code>TopLevelElement</code> or the
+ <code>Instruction</code> classes. (Both these classes extend the
+ <code>SyntaxTreeNode</code> class.)</p>
+
+ <p>The mapping from XSL element names to Java classes/AST nodes is set up
+ in the <code>initClasses()</code> method of the main parser:</p><source>
+ private void initStdClasses() {
try {
initStdClass("template", "Template");
initStdClass("param", "Param");
@@ -121,150 +167,215 @@
_classes.put(elementName,
Class.forName(COMPILER_PACKAGE + '.' + className));
}</source>
- </s3><anchor name="domxsl"/>
- <s3 title="Building a DOM tree from the input XSL file">
- <p>The parser instanciates a DOM that holds the input XSL stylesheet. The
- DOM can only handle XML files and will not break up and identify XPath
- patterns/expressions (these are stored as attributes to the various
- nodes in the tree) or calls to XSL functions(). Each XSL instruction gets
- its own node in the DOM, and the XPath patterns/expressions are stored as
- attributes of these nodes. A stylesheet looking like this:</p>
-<source>
+
+ </s3>
+
+ <anchor name="domxsl"/>
+ <s3 title="Building the AST from AST nodes">
+ <p>The parser builds an AST from the various syntax tree nodes. Each node
+ contains a reference to its parent node, a vector containing references
+ to all child nodes and a structure containing all attribute nodes:</p><source>
+ protected SyntaxTreeNode _parent; // Parent node
+ private Vector _contents; // Child nodes
+ protected Attributes _attributes; // Attributes of this element</source>
+
+
+ <p>These variables should be accessed using these methods:</p><source>
+ protected final SyntaxTreeNode getParent();
+ protected final Vector getContents();
+ protected String getAttribute(String qname);
+ protected Attributes getAttributes();</source>
+
+ <p>At this time the AST only contains nodes that represent the XSL elements
+ from the stylesheet. A SAX parse is generic and can only handle XML files
+ and will not break up and identify XPath patterns/expressions (these are
+ stored as attributes to the various nodes in the tree). Each XSL instruction
+ gets its own node in the AST, and the XPath patterns/expressions are stored
+ as attributes of these nodes. A stylesheet looking like this:</p><source>
<xsl:stylesheet .......>
<xsl:template match="chapter">
<xsl:text>Chapter</xsl:text>
<xslvalue-of select=".">
</xsl:template>
- </xsl>stylesheet>
-</source>
- <p>will be stored in the DOM as indicated in the following picture:</p>
- <p><img src="compiler_DOM.gif" alt="compiler_DOM.gif"/></p>
- <p><ref>Figure 1: DOM containing XSL stylesheet</ref></p>
- <p>The pattern '<code>match="chapter"</code>' and the expression
- '<code>select="."</code>' are stored as attributes for the nodes
- '<code>xsl:template</code>' and '<code>xsl:value-of</code>' respectively.
- These attributes are accessible through the DOM interface.</p>
- </s3>
- <s3 title="Creating the Abstract Syntax Tree from the DOM">
- <p>What we have to do next is to create a tree that also holds the XSL
- specific elements; XPath expressions and patterns (with possible filters)
- and calls to XSL functions. This is done by parsing the DOM and creating an
- instance of a subclass of 'SyntaxTreeNode' for each node in the DOM. A node
- in the DOM containing an XSL instruction (for example, "xsl:template") results in an
- instance of the correspoding class derived from the HashTable created by
- the parser (in this case in instance of the 'Template' class).</p>
-
- <p>Each class that inherits SyntaxTreeNode has a vector called
- '<code>_contents</code>' that holds references to all the children of the node
- (if any). Each node has a method called '<code>parseContents()</code>'. It is
- the responsibility of this method to parse any XPath expressions/patterns
- that are expected and found in the node's attributes. The XPath patterns
- and instructions are tokenised using the auto-generated class 'XPathParser'
- (generated using JavaCup and JLex). The tokenised expressions/patterns
- will result in a small sub-tree owned by the syntax tree node.</p>
-
- <p>XSL nodes holding expressions has a pointer called '<code>_select</code>' that
- points to a sub-tree representing the expression. This can be seen for
- instance in the 'Template' class:</p>
- <p><img src="compiler_AST.gif" alt="compiler_AST.gif"/></p>
- <p><ref>Fiugre 2: Sample Abstract Syntax Tree</ref></p>
- <p>In this example _select only points to a single node. In more complex
- expressions the pointer will point to an whole sub-tree.</p>
- </s3>
- </s2><anchor name="typecheck"/>
- <s2 title="Type-check and Cast Expressions">
+ </xsl>stylesheet></source>
+
+ <p>will be stored in the AST as indicated in the following picture:</p>
+ <p><img src="ast_stage1.gif" alt="ast_stage1.gif"/></p>
+ <p><ref>Figure 1: The AST in its first stage</ref></p>
+
+ <p>All objects that make up the nodes in the initial AST have a
+ <code>parseContents()</code> method. This method is responsible for:</p>
+
+ <ul>
+ <li>parsing the values of those attributes that contain XPath expressions
+ or patterns, breaking each expression/pattern into AST nodes and inserting
+ them into the tree.</li>
+ <li>reading/checking all other required attributes</li>
+ <li>propagate the <code>parseContents()</code> call down the tree</li>
+ </ul>
+ </s3>
+
+ <s3 title="Mapping XPath expressions and patterns to additional AST nodes">
+
+ <p>The nodes that represent the XPath expressions and patterns extend
+ either the <code>Expression</code> or <code>Pattern</code> class
+ respectively. These nodes are not appended to the <code>_contents</code>
+ vectory of each node, but rather stored as individual references in each
+ AST <u>element</u> node. One example is the <code>ForEach</code> class that
+ represents the <code><xsl:for-each></code> element. This class has
+ a variable that contains a reference to the AST sub-tree that represents
+ its <code>select</code> attribute:</p><source>
+ private Expression _select;</source>
+
+ <p>There is no standard way of storing these XPath expressions and each
+ AST node that contains one or more XPath expression/pattern must handle
+ that itself. This <i>handling</i> basically involves passing the attribute's
+ value to the XPath parser and receiving back an AST sub-tree.</p>
+
+ <p>With all XPath expressions/patterns expanded, the AST will look somewhat
+ like this:</p>
+
+ <p><img src="ast_stage2.gif" alt="ast_stage2.gif"/></p>
+ <p><ref>Fiugre 2: The AST in its second stage</ref></p>
+
+ </s3>
+ </s2>
+
+ <!--================= TYPE CONVERSION SECTION ========================-->
+
+ <anchor name="typecheck"/>
+ <s2 title="Type-check and Cast Expressions">
+
<p>In many cases we will need to typecast the top node in the expression
sub-tree to suit the expected result-type of the expression, or to typecast
child nodes to suit the allowed types for the various operators in the
expression. This is done by calling 'typeCheck()' on the root-node in the
- XSL tree. Each SyntaxTree node is responsible for its own type checking
- (ie. the <code>typeCheck()</code> method must be overridden). Let us say that
- our pattern was:</p>
- <p><code><xsl:value-of select="1+2.73"/></code></p>
- <p><img src="typecast.gif" alt="typecast.gif"/></p>
- <p><ref>Figure 3: XPath expression type conflict</ref></p>
- <p>The number 1 is an integer, and the number 2.73 is a real number, so the
- 1 has to be promoted to a real. This is done ny inserting a new node between
- the [1] and the [+]. This node will convert the 1 to a real number:</p>
- <p><img src="cast_expression.gif" alt="cast_expression.gif"/></p>
- <p><ref>Figure 4: Type casting</ref></p>
-
- <p>The inserted node is an object of the class CastExpr. The SymbolTable
- that was instanciated in (1) is used to determine what casts are needed for
- the various operators and what return types the various expressions will
- have.</p>
-
- </s2><anchor name="compile"/>
- <s2 title="Code generation">
- <ul>
- <li><link anchor="toplevelelem">Compiling top-level elements</link></li>
- <li><link anchor="templatecode">Compiling template code</link></li>
- <li><link anchor="instrfunc">Compiling XSL instructions and functions</link></li>
- </ul>
- <p>A general rule is that all classes that represent elements in the XSL
- tree/document, i.e., classes that inherit from SyntaxTreeNode, output
- bytecode in the 'translate()' method.</p>
- <anchor name="toplevelelem"/>
+ XSL tree. Each SyntaxTreeNode node is responsible for inserting type-cast
+ nodes between itself and its child nodes or XPath nodes. These type-cast
+ nodes will convert the output-types of the child/XPath nodes to the expected
+ input-type of the parent node. Let look at our AST again and the node that
+ represents the <code><xsl:value-of></code> element. This element
+ expects to receive a string from its <code>select</code> XPath expression,
+ but the <code>Step</code> expression will return either a node-set or a
+ single node. An extra node is inserted into the AST to perform the
+ necessary type conversions:</p>
+
+ <p><img src="ast_stage3.gif" alt="ast_stage3.gif"/></p>
+ <p><ref>Figure 3: XPath expression type cast</ref></p>
+
+ <p>The <code>typeCheck()</code> method of each SyntaxTreeNode object will
+ call <code>typeCheck()</code> on each of its XPath expressions. This method
+ will return the native type returned by the expression. The AST node will
+ insert an additional type-conversion node if the return-type does not match
+ the expected data-type. Each possible return type is represented by a class
+ in the <code>org.apache.xalan.xsltc.compiler.util</code> package. These
+ classes all contain methods that will generate bytecodes needed to perform
+ the actual type conversions (at runtime). The type-cast nodes in the AST
+ mainly consist of calls to these methods.</p>
+ </s2>
+
+ <!--=============== BYTE-CODE GENERATION SECTION ======================-->
+
+ <anchor name="compile"/>
+ <s2 title="JVM byte-code generation">
+
+ <ul>
+ <li><link anchor="stylesheet">Compiling the stylesheet</link></li>
+ <li><link anchor="toplevel">Compiling top-level elements</link></li>
+ <li><link anchor="templates">Compiling template code</link></li>
+ <li><link anchor="instructions">Compiling instructions, functions expressions and patterns</link></li>
+ </ul>
+
+ <p>Evey node in the AST extends the <code>SyntaxTreeNode</code> base class
+ and implements the <code>translate()</code> method. This method is
+ responsible for outputting the actual bytecodes that make up the
+ functionality required for each element, function, expression or pattern.
+ </p>
+
+ <anchor name="stylesheet"/>
+ <s3 title="Compiling the stylesheet">
+ <p>Some nodes in the AST require more complex code than others. The best
+ example is the <code><xsl:stylesheet></code> element. The code that
+ represents this element has to tie together the code that is generated by
+ all the other elements and generate the actual class definition for the main
+ translet class. The <code>Stylesheet</code> class generates the translet's
+ constructor and methods that handle all top-level elements.</p>
+ </s3>
+
+ <anchor name="toplevel"/>
<s3 title="Compiling top-level elements">
<p>The bytecode that handles top-level elements must be generated before any
- other code. The '<code>translate()</code>' method in these classes are mainly
- called from these methods in the Stylesheet class:</p>
-
-<source> private String compileBuildKeys(ClassGenerator classGen);
- private String compileTopLevel(ClassGenerator classGen, Enumeration elements);
- private void compileConstructor(ClassGenerator classGen, Output output);</source>
+ other code. The '<code>translate()</code>' method in these classes are
+ mainly called from these methods in the Stylesheet class:</p><source>
+ private String compileBuildKeys(ClassGenerator);
+ private String compileTopLevel(ClassGenerator, Enumeration);
+ private void compileConstructor(ClassGenerator, Output);</source>
<p>These methods handle most top-level elements, such as global variables
and parameters, <code><xsl:output></code> and
<code><xsl:decimal-format></code> instructions.</p>
- </s3><anchor name="templatecode"/>
+ </s3>
+
+ <anchor name="templates"/>
<s3 title="Compiling template code">
- <p>All XPath patterns in <code><xsl:apply-template></code> instructions
- are converted into numeric values (known as the pattern's kernel 'type').
- All templates with identical pattern kernel types are grouped together and
- inserted into a table with its assigned type. (This table is found in the
- Mode class. There will be one such table for each mode that is used in the
- stylesheet). This table is used to build a big <code>switch()</code> statement
- in the translet's <code>applyTemplates()</code> method. This method is initially
- called with the root node of the input document.</p>
- <p>The <code>applyTemplates()</code> method determines the node's type and passes
- this type to the <code>switch()</code> statement to look up the matching
- template.</p>
+ <p>All XPath patterns in <code><xsl:apply-template></code>
+ instructions are converted into numeric values (known as the pattern's
+ kernel 'type'). All templates with identical pattern kernel types are
+ grouped together and inserted into a table known as a test sequence.
+ (The table of test sequences is found in the Mode class in the compiler
+ package. There will be one such table for each mode that is used in the
+ stylesheet). This table is used to build a big <code>switch()</code>
+ statement in the translet's <code>applyTemplates()</code> method. This
+ method is initially called with the root node of the input document.</p>
+
+ <p>The <code>applyTemplates()</code> method determines the node's type and
+ passes this type to the <code>switch()</code> statement to look up the
+ matching template. The test sequence code (the <code>TestSeq</code> class)
+ is responsible for inserting bytecodes to find <u>one</u> matching template
+ in cases where more than one template matches the current node type.</p>
<p>There may be several templates that share the same pattern kernel type.
Here are a few examples of templates with patterns that all have the same
- kernel type:</p>
-
-<source> <xsl:template match="A/C">
+ kernel type:</p><source>
+ <xsl:template match="A/C">
<xsl:template match="A/B/C">
<xsl:template match="A | C"></source>
- <p>All these templates will be grouped under the type for <code><C></code>
- and will all get the same kernel type (the type for <code>"C"</code>). The last
- template will be grouped both under <code>"C"</code> and <code>"A"</code>. If the
- type identifier for <code>"C"</code> in this case is 8, all these templates will
- be put under <code>case 8:</code> in <code>applyTemplates()</code>'s big
- <code>switch()</code> statement. The Mode class will insert extra code to choose
- which template code to invoke.</p>
- </s3><anchor name="instrfunc"/>
- <s3 title="Compiling XSL instructions and functions">
-
- <p>The template code is generated by calling <code>translate()</code> on each
- Template object in the abstract syntax tree. This call will be propagated
- down the tree and every element will output the bytecodes necessary to
- complete its task.</p>
-
- <p>Each node will call 'translate()' on its children, and possibly on
- objects representing the node's XPath expressions, before outputting its
- own bytecode. In that way the correct sequence of instructions is generated.
- Each one of the child nodes is responsible of creating code that leaves the
- node's output value (if any) on the stack. The typical procedure for the
- parent node is to create code that consumes these values off the stack and
- then leave its own output on the stack for its parent.</p>
+ <p>All these templates will be grouped under the type for
+ <code><C></code> and will all get the same kernel type (the type for
+ <code>"C"</code>). The last template will be grouped both under
+ <code>"C"</code> and <code>"A"</code>, since it matches either element.
+ If the type identifier for <code>"C"</code> in this case is 8, all these
+ templates will be put under <code>case 8:</code> in
+ <code>applyTemplates()</code>'s big <code>switch()</code> statement. The
+ <code>TestSeq</code> class will insert some code under the
+ <code>case 8:</code> statement (similar to if's and then's) in order to
+ determine which of the three templates to trigger.</p>
+ </s3>
+
+ <anchor name="instructions"/>
+ <s3 title="Compiling instructions, functions, expressions and patterns">
+
+ <p>The template code is generated by calling <code>translate()</code> on
+ each <code>Template</code> object in the abstract syntax tree. This call
+ will be propagated down the abstract syntax tree and every element will
+ output the bytecodes necessary to complete its task.</p>
+
+ <p>The Java Virtual Machine is stack-based, which goes hand-in-hand with
+ the tree structure of a stylesheet and the AST. A node in the AST will
+ call <code>translate()</code> on its child nodes and any XPath nodes before
+ it generates its own bytecodes. In that way the correct sequence of JVM
+ instructions is generated. Each one of the child nodes is responsible of
+ creating code that leaves the node's output value (if any) on the stack.
+ The typical procedure for the parent node is to create JVM code that
+ consumes these values off the stack and then leave its own output on the
+ stack (for its parent).</p>
<p>The tree-structure of the stylesheet is in this way closely tied with
the stack-based JVM. The design does not offer any obvious way of extending
- the compiler to output code for other VMs or processors.</p>
- </s3>
+ the compiler to output code for other non-stack-based VMs or processors.</p>
+ </s3>
+
</s2>
+
</s1>
1.2 +6 -2 xml-xalan/java/xdocs/sources/xsltc/xsltc_runtime.xml
Index: xsltc_runtime.xml
===================================================================
RCS file: /home/cvs/xml-xalan/java/xdocs/sources/xsltc/xsltc_runtime.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- xsltc_runtime.xml 2001/05/04 20:20:43 1.1
+++ xsltc_runtime.xml 2001/12/14 13:09:56 1.2
@@ -56,16 +56,20 @@
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
-->
- <s1 title="XSLTC runtime environment">
+
+<s1 title="XSLTC runtime environment">
<ul>
<li><link anchor="overview">Runtime overview</link></li>
<li><link anchor="translet">The compiled translet</link></li>
<li><link anchor="types">External/internal type mapping</link></li>
<li><link anchor="mainloop">Main program loop</link></li>
-
</ul>
+
+ <!--=================== OVERVIEW SECTION ===========================-->
+
<anchor name="overview"/>
<s2 title="Runtime overview">
+
<p>The actual transformation of the input XML document is initiated by
one of these classes:</p>
1.5 +563 -632 xml-xalan/java/xdocs/sources/xsltc/xsltc_trax.xml
Index: xsltc_trax.xml
===================================================================
RCS file: /home/cvs/xml-xalan/java/xdocs/sources/xsltc/xsltc_trax.xml,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- xsltc_trax.xml 2001/09/13 18:43:20 1.4
+++ xsltc_trax.xml 2001/12/14 13:09:56 1.5
@@ -1,10 +1,11 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE s1 SYSTEM "../../style/dtd/document.dtd">
-<!--
+
+<!--
* The Apache Software License, Version 1.1
*
*
- * Copyright (c) 2001 The Apache Software Foundation. All rights
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -12,7 +13,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
@@ -20,7 +21,7 @@
* distribution.
*
* 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
+ * if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
@@ -28,7 +29,7 @@
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
- * software without prior written permission. For written
+ * software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
@@ -51,641 +52,571 @@
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 2001, Sun
- * Microsystems., http://www.sun.com. For more
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
-->
-<s1 title="The Translet API & TrAX">
-<p><ref>By</ref> <jump href="mailto:todd.miller@east.sun.com">G. Todd Miller</jump> -updated May 11, 2001</p>
-<ul>
- <li><link anchor="abstract">Abstract</link></li>
- <li><link anchor="trax">TrAX</link></li>
- <li><link anchor="integrate">Translet Integration</link></li>
- <li><link anchor="factory">SAXTransformerFactory for Translets</link></li>
- <li><link anchor="transform">AbstractTranslet transform() method</link></li>
- <li><link anchor="conclusion">Conclusion</link></li>
- <li><link anchor="appendix">Appendix</link></li>
-</ul>
-<p>See also: <jump href="../xsltc_usage.html#api">Calling XSLTC with the TrAX/JAXP API</jump></p>
-<anchor name="abstract"/>
-<s2 title="Abstract">
-<p>This document describes what I have so far as a prototype for integrating
-Translets with the JAXP TrAX. In a nutshell, a new Transformer factory
-class has be written that extends the JAXP SAXTransformerFactory class.
-The newfactory delivers Translets as Transformers, and creates Templates.
-Calling the Transformer transform() method will cause the given XML
-document to be transformed by a translet that has been compiled from the
-supplied stylesheet. The switch that determines what XSLT processor gets
-to transform the XML document is based on the value of a JAXP system
-property for the Transformers factory.</p>
-</s2><anchor name="trax"/>
-<s2 title="TrAX">
-<p>The Java API for XML Processing (JAXP) includes an XSLT framework based on the
-Transformation API for XML (TrAX). In a typical JAXP transformation application
-the steps involved in transforming an XML document with an XSLT stylesheet are: (1)
-create an instance of the TransformerFactory class, (2) from the factory instance and
-a given XSLT stylesheet, create a new Transformer object, (3) call the Transformer
-objects transform() method on a given XML document and a specified Result object.
-Alternatively, one could also ask the instance of the TransformerFactory for
-a Templates object given an XSLT stylesheet. From the Templates object, a new
-Transformer can be created, and again, its transform() method can be called with
-an XML document and specified Result object.</p>
-<p>The code below illustrates a simple JAXP transformation application (Proto.java)
-that creates the Transformer directly.</p>
-<source>import javax.xml.transform.stream.StreamSource;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-
-public class Proto {
- public static void main(String[] args){
- Proto app = new Proto();
- app.run(args);
- }
-
- public void run(String[] args){
- if (args.length != 2) {
- usage();
- }
- String inputFilename = args[0];
- String stylesheet = args[1];
- Transformer transformer;
- TransformerFactory factory = TransformerFactory.newInstance();
- try {
- transformer = factory.newTransformer(new StreamSource(stylesheet));
- transformer.transform(new StreamSource(inputFilename),
- new StreamResult(System.out));
- } catch (Exception e) {
- // nothing...
- }
- }
+<s1 title="The Translet API and TrAX">
- public void usage() {
- System.err.println(
- "Usage: run <xml_file> <xsl_file>");
- System.exit(1);
- }
-}</source>
-<p>The use of Templates is useful when multiple instances of the same transformer
-are needed. For example transforming multiple documents by the same transformer,
-each working in a separate thread. In this case, the TransformerFactory is used to
-create a Templates object for a given stylesheet. Each Transformer instance is then
-created by the Templates object. In this way the Templates object can compile the
-stylesheet once, and each time a new instance of the transformer is asked for, a clone is
-provided rather than recompile the stylesheet again and again. The Proto class above
-would be modified as follows:</p>
-<source>try {
- Templates templates = factory.newTemplates(new StreamSource(stylesheet));
- transformer = templates.newTransformer();
- transformer.transform(new StreamSource(inputFilename),
- new StreamResult(System.out));
-} catch (Exception e) {
- // nothing...
-}</source>
-<p>The JAXP TransformerFactory is configurable. The API supports configuring the
-factory to: (1) use attributes which are passed down to the underlying XSL processor,
-these are vendor dependent, (2) register an ErrorListener that provides callbacks
-to handle error and warning message generated by the XSL processor, (3) register
-an URIResolver which can be used to resolve URIs encountered in xsl:include,
-xsl:import,anddocument() functions.</p>
-<p>The JAXP TransformerFactory can be queried at runtme to discover what features
-it supports. For example, an application might want to know if a particular factory
-implementation supports the use of SAX events as a source, or whether it can write
-out transformation results as a DOM. The factory API queries with the getFeature()
-method. In the Proto code above, I could add the following code before the try-catch
-block:</p>
-<source>if (!(factory.getFeature(StreamSource.FEATURE)) ||
- !(factory.getFeature(StreamResult.FEATURE))) {
- System.err.println(
- "Stream Source/Result not supported by Transformer Factory\n" +
- "exiting.");
- System.exit(1);
-}</source>
-</s2><anchor name="integrate"/>
-<s2 title="Translet Integration">
-<p>The crux of the integration strategy is the pluggable TransformerFactory class. The
-JAXP specifies that the actual TransformerFactory implementation be controlled by the
-a Java system property (javax.xml.transform.TransformerFactory) . This system property can be specified in the usual ways, for
-example in a properties file or on the command line as a -D option passed to the java
-engine itself. The strategy involves writing a TransformerFactory for Translets.
-In the JAXP the TransformerFactory is an abstract class. In Xalan, the system
-property specifies the implementation class TransformerFactoryImpl (org.apache.xalan.processor.TransformerFactoryImpl).
- This implementation is an extension of the abstract SAXTransformerFactory class, which in
-turn is an extension of the abstract TransformerFactory class (javax.xml.transform.sax.SAXTransformerFactory).</p>
-<p>In this prototype integration I have constructed an XSLTC TransformerFactory as
-an extension of the abstract SAXTransformerFactory class.</p>
-
-</s2><anchor name="factory"/>
-<s2 title="SAXTransformerFactory for Translets">
-<p>The prototype XSLTC TransformerFactory needs to accomplish the following:</p>
- <ul>
- <li><link anchor="saxtransformerfactory">Implement the abstract methods of the SAXTransformerFactory class</link></li>
- <li><link anchor="transformerfactory">Implement the abstract methods of the TransformerFactory class</link></li></ul>
-<anchor name="saxtransformerfactory"/>
-<s3 title="SAXTransformerFactory Methods">
-
-<p>The methods of the abstract SAXTransformerFactory class have been stubbed out as
-follows.</p>
-<source>public TemplatesHandler newTemplatesHandler() { return null; }
-public TransformerHandler newTransformerHandler() { return null; }
-public TransformerHandler newTransformerHandler(Source src) {
-return null;
-}
-public TransformerHandler newTransformerHandler(Templates templates) {
-return null;
-}
-public XMLFilter newXMLFilter(Source src) { return null; }
-public XMLFilter newXMLFilter(Templates templates) { return null; }</source>
-<p>These stubbed out methods will need to be replaced with real implementations.</p>
-</s3><anchor name="transformerfactory"/>
-<s3 title="TransformerFactory Methods">
-<p>The methods of the abstract TransformerFactory class have been stubbed out as
-follows:</p>
-<source>public ErrorListener getErrorListener() { return null; }
-public void setErrorListener(ErrorListener listener) { }
-public Object getAttribute(String name) { return null; }
-public void setAttribute(String name, Object value) { }
-public boolean getFeature(String name) { return false; }
-public URIResolver getURIResolver() { return null; }
-public void setURIResolver(URIResolver resolver) { }
-public Source getAssociatedStylesheet(Source src, String media,
-String title, String charset) { return null; }
-public Templates newTemplates(Source xslSrc) throws
-TransformerConfigurationException { return null; }
-public Transformer newTransformer() throws
-TransformerConfigurationException { return null; }</source>
-<p>The methods listed above fall into 4 categories: (1) <link anchor="transformcreation">Transform creation</link>,
-(2) <link anchor="templatescreation">Templates creation</link>, (3) <link anchor="featurediscovery">feature discovery</link>,
-and (4) <link anchor="limitations">others that will remain unimplemented at this time</link>.</p>
-<anchor name="transformercreation"/>
-<s4 title="Transformer Creation">
-<p>The JAXP specifies a method that takes the stylesheet as a Source object and returns a
-Transformer.</p>
-<p><code>public Transformer newTransformer(Source xslSrc)</code></p>
-<p>This method needs to return a Transformer to comply with the JAXP API, but also
-needs to return a Translet. In the XSLTC/Xalan API, a Translet is an interface that is
-implemented by the runtime abstract class AbstractTranslet (org.apache.xalan.xsltc.Translet and org.apache.xalan.xsltc.runtime.AbstractTranslet, repectively). Therefore, I had to
-change the AbstractTranslet class so that it will extend the abstract Transformer
-class while still implementing the Translet interface. Once this is done, then the
-newTransformer() method of the new TransformerFactory can return a Translet that
-is a Transformer.</p>
-<p>In order to have AbstractTranslet extend Transformer, several abstract methods
-have to be implemented in AbstractTranslet class. These are:</p>
-<source>public void clearParameters() { }
-public ErrorListener getErrorListener() { return null; }
-public Properties getOutputProperties() throws IllegalArgumentException {
- return null;
-}
-public String getOutputProperty(String name)
- throws IllegalArgumentException{ return ""; }
-//public Object getParameter(String name) { return null; }
-public URIResolver getURIResolver() { return null; }
-public void setErrorListener(ErrorListener listener)
- throws IllegalArgumentException { }
-public void setOutputProperties(Properties props)
- throws IllegalArgumentException { }
-public void setOutputProperty(String name, String value)
- throws IllegalArgumentException { }
-public void setParameter(String name, Object value) { }
-public void setURIResolver(URIResolver resolver) { }
-public void transform(Source xmlsrc, Result outputTarget)
- throws TransformerException { ... }</source>
-<p>Mapping these methods to some existing ones in AbstractTranslet still has to be
-done. In particular the transform() method which is explained further in a following
-section.</p>
-<p>Now that XSLTC�s AbstractTranslet is a Transformer, the new Transformer
-factory class can implement the newTransformer() method. This method needs to do
-two fundamental things: (1) create a translet from the given XSLT stylesheet and (2)
-instantiate the translet so it can be returned as a Transformer.</p>
-<p>The code belows hows my current implementation of the newTransformer() method
-in the new factory class:</p>
-<source>public class ToddsTransformerFactoryImpl extends SAXTransformerFactory {
- ...
- public Transformer newTransformer(Source stylesheet) throws
- TransformerConfigurationException
- {
- XSLTC xsltc = new XSLTC();
- xsltc.init();
- String stylesheetName = stylesheet.getSystemId();
- int index = stylesheetName.indexOf(�.�);
- String transletName = stylesheetName.substring(0,index);
- boolean isSuccessful = true;
- try {
- File file = new File(stylesheetName);
- URL url = file.toURL();
- isSuccessful = xsltc.compile(url);
- } catch (MalformedURLException e) {
- throw new TransformerConfigurationException(
- "URL for stylesheet �" + stylesheetName +
- "� can not be formed.");
- }
+ <s2 title="Contents">
- if (!isSuccessful) {
- throw new TransformerConfigurationException(
- "Compilation of stylesheet �" + stylesheetName + "� failed.");
- }
-
- Translet translet = null;
+ <p>The structure of this document is, and should be kept, as follows:</p>
+
+ <ul>
+ <li>A brief introduction to TrAX/JAXP</li>
+ <li>Overall design of the XSLTC TrAX implementation</li>
+ <li>Detailed design of various TrAX components</li>
+ </ul>
+
+ <ul>
+ <li><link anchor="abstract">Abstract</link></li>
+ <li><link anchor="trax">TrAX basics</link></li>
+ <li><link anchor="config">TrAX configuration</link></li>
+ <li><link anchor="design">XSLTC TrAX architecture</link></li>
+ <li><link anchor="detailed_design">XSLTC TrAX detailed design</link>
+ <ul>
+ <li><link anchor="factory_design">TransformerFactory design</link></li>
+ <li><link anchor="templates_design">Templates design</link></li>
+ <li><link anchor="transformer_design">Transformer design</link></li>
+ <li><link anchor="config_design">TrAX configuration design</link></li>
+ </ul>
+ </li>
+ </ul>
+ </s2>
+
+ <!--====================== ABSTRACT SECTION ===========================-->
+
+ <anchor name="abstract"/>
+ <s2 title="Abstract">
+
+ <p>JAXP is the Java extension API for XML parsing. TrAX is an API for XML
+ transformations and is included in the later versions of JAXP. JAXP includes
+ two packages, one for XML parsing and one for XML transformations (TrAX):</p>
+<source>
+ javax.xml.parsers
+ javax.xml.transform</source>
+
+ <p>XSLTC is an XSLT processing engine and fulfills the role as an XML
+ transformation engine behind the TrAX portion of the JAXP API. XSLTC is a
+ provider for the TrAX API and a client of the JAXP parser API.</p>
+
+ <p>This document describes the design used for integrating XSLTC translets
+ with the JAXP TrAX API. The heart of the design is a wrapper class around the
+ XSLTC compiler that extends the JAXP <code>SAXTransformerFactory</code>
+ interface. This factory delivers translet class definitions (Java bytecodes)
+ wrapped inside TrAX <code>Templates</code> objects. These
+ <code>Templates</code> objects can be used to instanciate
+ <code>Transformer</code> objects that transform XML documents into markup or
+ plain text. Alternatively a <code>Transformer</code> object can be created
+ directly by the <code>TransformerFactory</code>, but this approach is not
+ recommended with XSLTC. The reason for this will be explained later in this
+ document.</p>
+
+ </s2>
+
+ <!--====================== TRAX BASICS SECTION =========================-->
+
+ <anchor name="trax"/>
+ <s2 title="TrAX basics">
+
+ <p>The Java API for XML Processing (JAXP) includes an XSLT framework based
+ on the Transformation API for XML (TrAX). A JAXP transformation application
+ can use the TrAX framework in two ways. The simplest way is:</p>
+
+ <ul>
+ <li>create an instance of the TransformerFactory class</li>
+ <li>from the factory instance and a given XSLT stylesheet, create a new
+ Transformer object</li>
+ <li>call the Transformer object's transform() method, specifying the XML
+ input and a Result object.</li>
+ </ul><source>
+ import javax.xml.transform.*;
+
+ public class Compile {
+
+ public void run(Source xsl) {
+ ....
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer(xsl);
+ ....
+ }
+ }</source>
+
+ <p>This suits most conventional XSLT processors that transform XML documents
+ in one go. XSLTC needs one extra step to compile the XSL stylesheet into a
+ Java class (a "translet"). Fortunately TrAX has another approach
+ that suits XSLTC two-step transformation model:</p>
+
+ <ul>
+ <li>create an instance of the TransformerFactory class</li>
+ <li>from the factory instance and a given XSLTC, stylesheet, create a new
+ Templates object (this step will compile the stylesheet and put the
+ bytecodes for translet class(es) into the Templates object)</li>
+ <li>from the Template object create a Transformer object (this will
+ instanciate a new translet object).</li>
+ <li>call the Transformer object's transform() method, specifying the XML
+ input and a Result object.</li>
+ </ul><source>
+ import javax.xml.transform.*;
+
+ public class Compile {
+
+ public void run(Source xsl) {
+ ....
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Templates templates = factory.newTemplates(xsl);
+ Transformer transformer = templates.newTransformer();
+ ....
+ }
+ }</source>
+
+ <p>Note that the first two steps need be performed only once for each
+ stylesheet. Once the stylesheet is compiled into a translet and wrapped in a
+ <code>Templates</code> object, the <code>Templates</code> object can be used
+ over and over again to create Transformer object (instances of the translet).
+ The <code>Templates</code> instances can even be serialized and stored on
+ stable storage (ie. in a memory or disk cache) for later use.</p>
+
+ <p>The code below illustrates a simple JAXP transformation application that
+ creates the <code>Transformer</code> directly. Remember that this is not the
+ ideal approach with XSLTC, as the stylesheet is compiled for each
+ transformation.</p><source>
+ import javax.xml.transform.stream.StreamSource;
+ import javax.xml.transform.stream.StreamResult;
+ import javax.xml.transform.Transformer;
+ import javax.xml.transform.TransformerFactory;
+
+ public class Proto {
+
+ public void run(String xmlfile, String xslfile) {
+ Transformer transformer;
+ TransformerFactory factory = TransformerFactory.newInstance();
+
+ try {
+ StreamSource stylesheet = new StreamSource(xslfile);
+ transformer = factory.newTransformer(stylesheet);
+ transformer.transform(new StreamSource(xmlfile),
+ new StreamResult(System.out));
+ }
+ catch (Exception e) {
+ // handle errors...
+ }
+ :
+ :
+ }</source>
+
+ <p>This approach seems simple is probably used in many applications. But, the
+ use of <code>Templates</code> objects is useful when multiple instances of
+ the same <code>Transformer</code> are needed. <code>Transformer</code>
+ objects are not thread safe, and if a server wants to handle several clients
+ requests it would be best off to create one global <code>Templates</code>
+ object, and then from this create a <code>Transformer</code> object for each
+ thread handling the requests. This approach is also by far the best for
+ XSLTC, as the <code>Templates</code> object will hold the class definitions
+ that make up the translet and its auxiliary classes. (Note that the bytecodes
+ and not the actuall class definitions are stored when serializing a
+ <code>Templates</code> object to disk. This is because of class loader
+ security restrictions.) To accomodate this second approach to TrAX
+ transformations, the above class would be modified as follows:</p><source>
try {
- Class clazz = Class.forName(transletName);
- translet = (Translet)clazz.newInstance();
- ((AbstractTranslet)translet).setTransletName(transletName);
- } catch (ClassNotFoundException e) {
- throw new TransformerConfigurationException(
- "Translet class �" + transletName + "� not found.");
- } catch (InstantiationException e) {
- throw new TransformerConfigurationException(
- "Translet class �" + transletName +
- "� could not be instantiated");
- } catch (IllegalAccessException e) {
- throw new TransformerConfigurationException(
- "Translet class �" + transletName + "� could not be accessed.");
- }
- return (AbstractTranslet)translet;
- }
-}</source>
-</s4><anchor name="templatescreation"/>
-<s4 title="Templates Creation">
-<p>The JAXP specifies a method that takes the stylesheet as a Source object and returns a
-Templates object.</p>
-<p><code>public Templates newTemplates(Source xslSrc)</code></p>
-<p>To implement this method I needed to create a new class that would be a Templates
-for Translets object. The new class TransletTemplates (org.apache.xalan.xsltc.trax.TransletTemplates) implements the Templates
-interface as is shown below:</p>
-<source>package org.apache.xalan.xsltc.trax;
-
-import javax.xml.transform.Templates;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import org.apache.xalan.xsltc.runtime.AbstractTranslet;
-import java.util.Properties;
-
-public class TransletTemplates implements Templates {
- public TransletTemplates(Transformer translet) {
- _translet = (AbstractTranslet)translet;
- }
-
- public Properties getOutputProperties() { /*TBD*/ return null; }
-
- public Transformer newTransformer() throws
- TransformerConfigurationException
- {
- if (_translet == null) {
- throw new TransformerConfigurationException(
- "Error: Null Translet");
- }
- return _translet;
- }
- private AbstractTranslet _translet = null;
-}</source>
-<p>The factory method newTemplates() simply creates a Transformer for the stylesheet,
-and returns a newTransletTemplates object. The implementation of newTemplates()
-is shown below:</p>
-<source>public class TransformerFactoryImpl extends SAXTransformerFactory {
-...
- public Templates newTemplates(Source stylesheet) throws
- TransformerConfigurationException
- {
- Transformer translet = newTransformer(stylesheet);
- return new TransletTemplates(translet);
- }
-}</source>
-<p>This implementation only satisfies the JAXP, it does not address caching of previously
-created translets. This type of mechanism belongs in Templates,where a given
-stylesheet will be compiled one time only, but the generated translet can be cloned to
-create multiple instances upon demand.</p>
-</s4><anchor name="featurediscovery"/>
-<s4 title="Feature Discovery">
-<p>The JAXP specifies a method that allows programs to discover what features the factory
-is capable of supporting.</p>
-<p><code>public boolean getFeature(String featureName)</code></p>
-<p>At this time the new transformer factory supports Stream sources and results, and
-the SAX Transform factory feature. The getFeature() implementation is shown below:</p>
-<source>public class TransformerFactoryImpl extends SAXTransformerFactory {
- ...
- public boolean getFeature(String name) {
- if ((StreamSource.FEATURE == name) ||
- (StreamResult.FEATURE == name) ||
- (SAXTransformerFactory.FEATURE == name)) {
- return true;
- } else if ((StreamSource.FEATURE.equals(name))
- || (StreamResult.FEATURE.equals(name))
- || (SAXTransformerFactory.FEATURE.equals(name))) {
- return true;
- } else {
- return false;
+ StreamSource stylesheet = new StreamSource(xslfile);
+ Templates templates = factory.newTemplates(stylesheet);
+ transformer = templates.newTransformer();
+ transformer.transform(new StreamSource(inputFilename),
+ new StreamResult(System.out));
}
- }
-}</source>
-<p>As the other features are implemented, this methods will need to be updated.</p>
-
-</s4><anchor name="limitations"/>
-<s4 title="Limitations">
-<p>As you can see, the prototype will compile the stylesheet everytime. This obviously
-needs to be smarter. This is where the question �do I already have this translet?� needs
-to be answered. Also for now the translet bytecodes are written out to a File in the current
-working directory, and then instantiated using a Class.forName, newInstance()
-pair. This also needs work. Note the return statement, the Translet is cast to an AbstractTranslet
-which now is a Transformer.</p>
-</s4>
-</s3>
-</s2><anchor name="transform"/>
-<s2 title="AbstractTranslet�s transform() Method">
-<p>Now the JAXP program (Proto) shown in the first section has a way to get a Transformer
-factory that can return Translets. The next step of the Proto.java program is
-calling the transform() method and having the Translet process the given XML
-document.</p>
-<p>This requires some surgery in the AbstractTranslet class again. The AbstractTranslet
-already has a transform() method, but its signature is not the same as the
-JAXP Transform signature. In the AbstractTranslet, transform methods expect a DOM
-argument, in some cases a NodeIterator, and a TransletOutputHandler argument. The
-JAXP Transform�s transform() signature requires only the XML document as a Source
-object reference and an outputTarget as a Result object reference. My implementation
-of the JAXP transform() signature is as shown:</p>
-
-<source>public void transform(Source xmlsrc, Result outputTarget)
- throws TransformerException
-{
- doTransform( xmlsrc.getSystemId(),
- ((StreamResult)outputTarget).getOutputStream() );
-}</source>
-<p>This implementation leverages code derived from XSLTC�s DefaultRun class. In
-that class there is a doTransform() method that carries out the work of: (1) parsing the
-input XML document (using a JAXP SAXParserFactory and SAXParser), (2) creating
-a DOMImpl (org.apache.xalan.xsltc.dom.DOMImpl), (3) creating a SAXOutputHandler, and finally (4) calling the translet to
-transform the input XML document (from the DOMImpl).</p>
-<p>The code for doTransform is shown below:</p>
-<source>public abstract class AbstractTranslet extends Transformer implements Translet{
- ...
- private void doTransform(String xmlDocName, OutputStream ostream) {
- try {
- final Translet translet = (Translet)this; // GTM added
+ catch (Exception e) {
+ // handle errors...
+ }</source>
- // Create a SAX parser and get the XMLReader object it uses
- final SAXParserFactory factory = SAXParserFactory.newInstance();
- final SAXParser parser = factory.newSAXParser();
- final XMLReader reader = parser.getXMLReader();
-
- // Set the DOM�s DOM builder as the XMLReader�s SAX2 content handler
- final DOMImpl dom = new DOMImpl();
- reader.setContentHandler(dom.getBuilder());
- // Create a DTD monitor and pass it to the XMLReader object
- final DTDMonitor dtdMonitor = new DTDMonitor();
- dtdMonitor.handleDTD(reader);
- dom.setDocumentURI(xmlDocName);
- /****************
- if (_uri)
- reader.parse(xmlDocName);
- else
- *******************/
- reader.parse("file:"+(new File(xmlDocName).getAbsolutePath()));
-
- // Set size of key/id indices
- setIndexSize(dom.getSize());
- // If there are any elements with ID attributes, build an index
- dtdMonitor.buildIdIndex(dom, 0, this);
+ </s2>
- setUnparsedEntityURIs(dtdMonitor.getUnparsedEntityURIs());
-
- // Transform the document
- String encoding = translet.getOutputEncoding();
- if (encoding == null) encoding = "UTF-8";
-
- //TextOutput textOutput = new TextOutput(System.out, encoding);
- DefaultSAXOutputHandler saxHandler = new
- DefaultSAXOutputHandler(ostream, encoding);
- TextOutput textOutput = new TextOutput(saxHandler, encoding);
- translet.transform(dom, textOutput);
- textOutput.flush();
- }
- catch (TransletException e) {
- ...
- }
- catch (RuntimeException e) {
- ...
- }
- catch (FileNotFoundException e) {
- ...
- }
- catch (MalformedURLException e) {
- ...
- }
- catch (UnknownHostException e) {
- ...
- }
- catch (Exception e) {
- ...
- }
- }
-}</source>
-</s2><anchor name="conclusion"/>
-<s2 title="Conclusion">
-<p>This is the current state of the integration of Translet and TrAX. The JAXP program
-illustrated in the first section (Proto.java) compiles and runs with the changes outlined
-above. The new transformer factory TransformerFactoryImpl supports transformer,
-templates creation, and the feature discovery mechanism. The transformers
-returned from the factory are in fact AbstractTranslet objects. The new class
-TransletTemplates implements the Templates interface for translets. This is the
-result of a first pass implementation, there are many stubbed out methods that need to
-be implemented, translet caching in Templates needs to be implemented and support
-for Source and Result types beyond simple stream types, such as DOM and SAX.</p>
-
-</s2><anchor name="appendix"/>
-<s2 title="Appendix">
-<ul>
- <li><link anchor="runscript">The Run script</link></li>
- <li><link anchor="transformerfactoryimpl">TransformerFactoryImpl.java</link></li>
- <li><link anchor="TransletTemplates">TransletTemplates.java</link></li>
- <li><link anchor="makefile">The Makefile</link></li>
-</ul>
-<anchor name="runscript"/>
-<s3 title="The Run script">
-<p>By changing the FAC variable I can switch between the two Transformer factory implementations
-for testing.</p>
-<source>#!/bin/ksh
-JAXP=/usr/local/jaxp-1.1/jaxp.jar
-CRIMSON=/usr/local/jaxp-1.1/crimson.jar
-XSLT=/net/bigblock/files18/tmiller/xml-xalan/java/build/classes
-XML=/net/bigblock/files18/tmiller/xml-xalan/java/bin/xml.jar
-BCEL=/net/bigblock/files18/tmiller/xml-xalan/java/bin/BCEL.jar
-JCUP=/net/bigblock/files18/tmiller/xml-xalan/java/bin/java_cup.jar
-JCUPRT=/net/bigblock/files18/tmiller/xml-xalan/java/bin/runtime.jar
-CLASSPATH=${JAXP}:${CRIMSON}:${XSLT}:${XML}:${BCEL}:${JCUP}:${JCUPRT}:.
-FAC=org.apache.xalan.xsltc.trax.TransformerFactoryImpl
-#FAC=org.apache.xalan.processor.TransformerFactoryImpl
-java -classpath ${CLASSPATH} \
- -Djavax.xml.transform.TransformerFactory=${FAC} \
- Proto $@</source>
-</s3><anchor name="transformerfactoryimpl"/>
-<s3 title="TransformerFactoryImpl.java">
-
-<source>package org.apache.xalan.xsltc.trax;
-
-import javax.xml.transform.Templates;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.ErrorListener;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.URIResolver;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TemplatesHandler;
-import javax.xml.transform.sax.TransformerHandler;
-
-import org.xml.sax.XMLFilter;
-
-import org.apache.xalan.xsltc.Translet;
-import org.apache.xalan.xsltc.compiler.XSLTC;
-import org.apache.xalan.xsltc.runtime.AbstractTranslet;
-
-import java.io.File;
-import java.net.URL;
-import java.net.MalformedURLException;
-
-/**
- * Implementation of a JAXP1.1 SAXTransformerFactory for Translets.
- */
-public class TransformerFactoryImpl extends SAXTransformerFactory {
- public TransformerFactoryImpl() { /* nothing yet */ }
-
- //////////////////////////////////////////////////////
- // SAXTransformerFactory (subclass of TransformerFactory)
- //
- public TemplatesHandler newTemplatesHandler() { /*TBD*/ return null; }
- public TransformerHandler newTransformerHandler() { /*TBD*/ return null; }
- public TransformerHandler newTransformerHandler(Source src) {
- /*TBD*/ return null;
- }
- public TransformerHandler newTransformerHandler(Templates templates) {
- /*TBD*/ return null;
- }
- public XMLFilter newXMLFilter(Source src) { /*TBD*/ return null; }
- public XMLFilter newXMLFilter(Templates templates) { /*TBD*/ return null; }
-
- //
- // End SAXTransformerFactory methods
- //////////////////////////////////////////////////////
- //////////////////////////////////////////////////////
- // TransformerFactory
- //
- public ErrorListener getErrorListener() { /*TBD*/ return null; }
- public void setErrorListener(ErrorListener listener) {/*TBD*/ }
- public Object getAttribute(String name) { /*TBD*/ return null; }
- public void setAttribute(String name, Object value) { /*TBD*/ }
- public boolean getFeature(String name) {
- if ((StreamSource.FEATURE == name) ||
- (StreamResult.FEATURE == name) ||
- (SAXTransformerFactory.FEATURE == name)) {
- return true;
- } else if ((StreamSource.FEATURE.equals(name))
- || (StreamResult.FEATURE.equals(name))
- || (SAXTransformerFactory.FEATURE.equals(name))) {
- return true;
- } else {
- return false;
- }
- }
- public URIResolver getURIResolver() { /*TBD*/ return null; }
- public void setURIResolver(URIResolver resolver) {/*TBD*/ }
- public Source getAssociatedStylesheet(Source src, String media,
- String title, String charset) { /*TBD*/ return null; }
- public Transformer newTransformer() throws
- TransformerConfigurationException { /*TBD*/ return null; }
- //
- // End TransformerFactory methods
- //////////////////////////////////////////////////////
- public Transformer newTransformer(Source stylesheet) throws
- TransformerConfigurationException
- {
- XSLTC xsltc = new XSLTC();
- xsltc.init();
- String stylesheetName = stylesheet.getSystemId();
- int index = stylesheetName.indexOf(�.�);
- String transletName = stylesheetName.substring(0,index);
- boolean isSuccessful = true;
- try {
- File file = new File(stylesheetName);
- URL url = file.toURL();
- isSuccessful = xsltc.compile(url);
- } catch (MalformedURLException e) {
- throw new TransformerConfigurationException(
- "URL for stylesheet �" + stylesheetName +
- "� can not be formed.");
- }
- if (!isSuccessful) {
- throw new TransformerConfigurationException(
- "Compilation of stylesheet �" + stylesheetName + "� failed.");
- }
+ <!--====================== TRAX CONFIG SECTION =========================-->
+
+ <anchor name="config"/>
+ <s2 title="TrAX configuration">
+
+ <p>JAXP's <code>TransformerFactory</code> is configurable similar to the
+ other Java extensions. The API supports configuring thefactory by:</p>
+
+ <ul>
+ <li>passing vendor-specific attributes from the application, through the
+ TrAX interface, to the underlying XSL processor</li>
+ <li>registering an ErrorListener that will be used to pass error and
+ warning messages from the XSL processor to the application</li>
+ <li>registering an URIResolver that the application can use to load XSL
+ and XML documents on behalf of the XSL processor (the XSL processor will
+ use this to support the xsl:include and xsl:import elements and the
+ document() functions.</li>
+ </ul>
+
+ <p>The JAXP TransformerFactory can be queried at runtime to discover what
+ features it supports. For example, an application might want to know if a
+ particular factory implementation supports the use of SAX events as a source,
+ or whether it can write out transformation results as a DOM. The factory API
+ queries with the getFeature() method. In the above code, we could add the
+ following code before the try-catch block:</p><source>
+ if (!factory.getFeature(StreamSource.FEATURE) || !factory.getFeature(StreamResult.FEATURE)) {
+ System.err.println("Stream Source/Result not supported by TransformerFactory\nExiting....");
+ System.exit(1);
+ }</source>
+
+ <p>Other elements in the TrAX API are configurable. A Transformer object can
+ be passed settings that override the default output settings and the settings
+ defined in the stylesheet for indentation, output document type, etc.</p>
+
+ </s2>
+
+ <!--====================== ARCHITECTURE SECTION ========================-->
+
+ <anchor name="design"/>
+ <s2 title="XSLTC TrAX architecture">
+
+ <p>XSLTC's architecture fits nicely in behind the TrAX interface. XSLTC's
+ compiler is put behind the <code>TransformerFactory</code> interface, the
+ translet <i>class definition</i> (either as a set of in-memory
+ <code>Class</code> objects or as a two-dimmensional array of bytecodes on
+ disk) is encapsulated in the <code>Templates</code> implementation and the
+ instanciated translet object is wrapped inside the <code>Transformer</code>
+ implementation. Figure 1 (below) shows this two-layered TrAX architecture:
+ </p>
+
+ <p><img src="trax_translet_wrapping.gif" alt="TransletWrapping"/></p>
+ <p><ref>Figure 1: Translet class definitions are wrapped inside Templates objects</ref></p>
+
+ <p>The <code>TransformerFactory</code> implementation also implements the
+ <code>SAXTransformerFactory</code> and <code>ErrorListener</code>
+ interfaces from the TrAX API.</p>
+
+ <p>The TrAX implementation has intentionally been kept completely separate
+ from the XSLTC native code. This prevents users of XSLTC's native API from
+ having to include the TrAX code in an application. All the code that makes
+ up our TrAX implementation resides in this package:</p><source>
+ org.apache.xalan.xsltc.trax</source>
+
+ <p>Message to all XSLTC developers: <u><i>Keep it this way! Do not mix TrAX
+ and Native code!</i></u></p>
+
+ </s2>
+
+ <!--======================= TRAX DESIGN SECTION ========================-->
+
+ <anchor name="detailed_design"/>
+ <s2 title="TrAX implementation details">
+
+ <p>The main components of our TrAX implementation are:</p>
+
+ <ul>
+ <li><link anchor="transformer_factory">the TransformerFactory class</link></li>
+ <li><link anchor="templates">the Templates class</link></li>
+ <li><link anchor="transformer">the Transformer class</link></li>
+ <li><link anchor="transformer">output properties handling</link></li>
+ </ul>
+
+ <anchor name="factory_design"/>
+ <s3 title="TransformerFactory implementation">
+
+ <p>The methods that make up the basic <code>TransformerFactory</code>
+ iterface are: </p><source>
+ public Templates newTemplates(Source source);
+ public Transformer newTransformer();
+ public ErrorListener getErrorListener();
+ public void setErrorListener(ErrorListener listener);
+ public Object getAttribute(String name);
+ public void setAttribute(String name, Object value);
+ public boolean getFeature(String name);
+ public URIResolver getURIResolver();
+ public void setURIResolver(URIResolver resolver);
+ public Source getAssociatedStylesheet(Source src, String media, String title, String charset);</source>
+
+ <p>And for the <code>SAXTransformerFactory</code> interface:</p><source>
+ public TemplatesHandler newTemplatesHandler();
+ public TransformerHandler newTransformerHandler();
+ public TransformerHandler newTransformerHandler(Source src);
+ public TransformerHandler newTransformerHandler(Templates templates);
+ public XMLFilter newXMLFilter(Source src);
+ public XMLFilter newXMLFilter(Templates templates);</source>
+
+ <p>And for the <code>ErrorListener</code> interface:</p><source>
+ public void error(TransformerException exception);
+ public void fatalError(TransformerException exception);
+ public void warning(TransformerException exception);</source>
+
+ <s4 title="TransformerFactory basics">
+ <p>The very core of XSLTC TrAX support for XSLTC is the implementation of
+ the basic <code>TransformerFactory</code> interface. This factory class is
+ more or less a wrapper around the the XSLTC compiler and creates
+ <code>Templates</code> objects in which compiled translet classes can
+ reside. These <code>Templates</code> objects can then be used to create
+ <code>Transformer</code> objects. In cases where the
+ <code>Transformer</code> is created directly by the factory we will use
+ the <code>Templates</code> class internally. In that way the transformation
+ will appear to be done in one step from the users point of view, while we
+ in reality use to steps. As described earler, this is not the best approach
+ when using XSLTC, as it causes the stylesheet to be compiled for each and
+ every transformation.</p>
+ </s4>
+
+ <s4 title="TransformerFactory attribute settings">
+ <p>The <code>getAttribute()</code> and <code>setAttribute()</code> methods
+ only recognise two attributes: <code>translet-name</code> and
+ <code>debug</code>. The latter is obvious - it forces XSLTC to output debug
+ information (dumps the stack in the very unlikely case of a failure). The
+ <code>translet-name</code> attribute can be used to set the default class
+ name for any nameless translet classes that the factory creates. A nameless
+ translet will, for instance, be created when the factory compiles a translet
+ for the identity transformation. There is a default name,
+ <code>GregorSamsa</code>, for nameless translets, so there is no absolute
+ need to set this attribute. (Gregor Samsa is the main character from Kafka's
+ "Metamorphosis" - transformations, metamorphosis - I am sure you
+ see the connection.)</p>
+ </s4>
+
+ <s4 title="TransformerFactory stylesheet handling">
+ <p>The compiler is can be passed a stylesheet through various methods in
+ the <code>TransformerFactory</code> interface. A stylesheet is passed in as
+ a <code>Source</code> object that containin either a DOM, a SAX parser or
+ a stream. The <code>getInputSource()</code> method handles all inputs and
+ converts them, if necessary, to SAX. The TrAX implementation contains an
+ adapter that will generate SAX events from a DOM, and this adapter is used
+ for DOM input. If the <code>Source</code> object contains a SAX parser, this
+ parser is just passed directly to the compiler. A SAX parse is instanciated
+ (using JAXP) if the <code>Source</code> object contains a stream.</p>
+ </s4>
+
+ <s4 title="TransformerFactory URI resolver">
+ <p>A TransformerFactory needs a <code>URIResolver</code> to locate documents
+ that are referenced in <code><xsl:import></code> and
+ <code><xsl:include></code> elements. XSLTC has an internal interface
+ that shares the same purpose. This internal interface is implemented by the
+ <code>TransformerFactory</code>:</p><source>
+ public InputSource loadSource(String href, String context, XSLTC xsltc);</source>
+ <p>This method will simply use any defined <code>URIResolver</code> and
+ proxy the call on to the URI resolver's <code>resolve()</code> method. This
+ method returns a <code>Source</code> object, which is converted to SAX
+ events and passed back to the compiler.</p>
+ </s4>
+
+ </s3>
+
+ <anchor name="template_design"/>
+ <s3 title="Templates design">
+
+ <s4 title="Templates creation">
+ <p>The <code>TransformerFactory</code> implementation invokes the XSLTC
+ compiler to generate the translet class and auxiliary classes. These classes
+ are stored inside our <code>Templates</code> implementation in a manner
+ which allows the <code>Templates</code> object to be serialized. By making
+ it possible to store <code>Templates</code> on stable storage we allow the
+ TrAX user to store/cache translet class(es), thus making room for XSLTC's
+ one-compilation-multiple-transformations approach. This was done by giving
+ the <code>Templates</code> implementation an array of byte-arrays that
+ contain the bytecodes for the translet class and its auxiliary classes. When
+ the user first requests a <code>Transformer</code> instance from the
+ <code>Templates</code> object for the first time we create one or more
+ <code>Class</code> objects from these byte arrays. Note that this is done
+ only once as long as the <code>Template</code> object resides in memory. The
+ <code>Templates</code> object then invokes the JVM's class loader with the
+ class definition(s) to instanciate the translet class(es). The translet
+ objects are then wraped inside a <code>Transformer</code> object, which is
+ returned to the client code:</p><source>
+
+ // Contains the name of the main translet class
+ private String _transletName = null;
+
+ // Contains the actual class definition for the translet class and
+ // any auxiliary classes (representing node sort records, predicates, etc.)
+ private byte[][] _bytecodes = null;
- Translet translet = null;
- try {
- Class clazz = Class.forName(transletName);
- translet = (Translet)clazz.newInstance();
- ((AbstractTranslet)translet).setTransletName(transletName);
- } catch (ClassNotFoundException e) {
- throw new TransformerConfigurationException(
- "Translet class �" + transletName + "� not found.");
- } catch (InstantiationException e) {
- throw new TransformerConfigurationException(
- "Translet class �" + transletName +
- "� could not be instantiated");
- } catch (IllegalAccessException e) {
- throw new TransformerConfigurationException(
- "Translet class �" + transletName + "� could not be accessed.");
- }
- return (AbstractTranslet)translet;
- }
- public Templates newTemplates(Source stylesheet) throws
- TransformerConfigurationException
- {
- Transformer translet = newTransformer(stylesheet);
- return new TransletTemplates(translet);
- }
-}</source>
-</s3><anchor name="translettemplates"/>
-<s3 title="TransletTemplates.java">
-<source>package org.apache.xalan.xsltc.trax;
-
-import javax.xml.transform.Templates;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.sax.SAXTransformerFactory;
-
-import org.apache.xalan.xsltc.runtime.AbstractTranslet;
-import java.util.Properties;
-
-/**
- * Implementation of a JAXP1.1 Templates object for Translets.
- */
-public class TransletTemplates implements Templates {
- public TransletTemplates(Transformer translet) {
- _translet = (AbstractTranslet)translet;
- }
- public Properties getOutputProperties() { /*TBD*/ return null; }
- public Transformer newTransformer() throws
- TransformerConfigurationException
- {
- if (_translet == null) {
- throw new TransformerConfigurationException(
- "Error: Null Translet");
- }
- return _translet;
- }
- private AbstractTranslet _translet = null;
-}</source>
-</s3><anchor name="makefile"/>
-<s3 title="The Makefile">
-<source>JAXP=/usr/local/jaxp-1.1/jaxp.jar
-CRIMSON=/usr/local/jaxp-1.1/crimson.jar
-XSLT=/net/bigblock/files18/tmiller/xml-xalan/java/build/classes
-CLASSPATH=${JAXP}:${CRIMSON}:${XSLT}
-SRCS=\
-Proto.java
-all:
-javac -classpath ${CLASSPATH} ${SRCS}</source>
-</s3>
-</s2>
+ /**
+ * Defines the translet class and auxiliary classes.
+ * Returns a reference to the Class object that defines the main class
+ */
+ private Class defineTransletClasses() {
+ TransletClassLoader loader = getTransletClassLoader();
+
+ try {
+ Class transletClass = null;
+ final int classCount = _bytecodes.length;
+ for (int i = 0; i < classCount; i++) {
+ Class clazz = loader.defineClass(_bytecodes[i]);
+ if (clazz.getName().equals(_transletName))
+ transletClass = clazz;
+ }
+ return transletClass; // Could still be 'null'
+ }
+ catch (ClassFormatError e) {
+ return null;
+ }
+ }</source>
+ </s4>
+
+ <s4 title="Translet class loader">
+
+ <p>The <code>Templates</code> object will create the actual translet
+ <code>Class</code> object(s) the first time the
+ <code>newTransformer()</code> method is called. (The "first time" means the
+ first time either after the object was instanciated or the first time after
+ it has been read from storage using serialization.) These class(es) cannot
+ be created using the standard class loader since the method:</p><source>
+ Class defineClass(String name, byte[] b, int off, int len);</source>
+
+ <p>of the ClassLoader is protected. XSLTC uses its own class loader that
+ extends the standard class loader:</p><source>
+ // Our own private class loader - builds Class definitions from bytecodes
+ private class TransletClassLoader extends ClassLoader {
+ public Class defineClass(byte[] b) {
+ return super.defineClass(null, b, 0, b.length);
+ }
+ }</source>
+ <p>This class loader is instanciated inside a privileged code section:</p><source>
+ TransletClassLoader loader =
+ (TransletClassLoader) AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ return new TransletClassLoader();
+ }
+ }
+ );</source>
+
+ <p>Then, when the newTransformer() method returns it passes back and
+ instance of XSLTC's <code>Transformer</code> implementation that contains
+ an instance of the main translet class. (One transformation may need several
+ Java classes - for sort-records, predicates, etc. - but there is always one
+ main translet class.)</p>
+
+ </s4>
+
+ <s4 title="Class loader security issues">
+
+ <p>When XSLTC is placed inside a JAR-file in the
+ <code>$JAVA_HOME/jre/lib/ext</code> it is loaded by the extensions class
+ loader and not the default (bootstrap) class loader. The extensions class
+ loader does not look for class files/definitions in the user's
+ <code>CLASSPATH</code>. This can cause two problems: A) XSLTC does not find
+ classes for external Java functions, and B) XSLTC does not find translet or
+ auxiliary classes when used through the native API.</p>
+
+ <p>Both of these problems are caused by XSLTC internally calling the
+ <code>Class.forName()</code> method. This method will use the current class
+ loader to locate the desired class (be it an external Java class or a
+ translet/aux class). This is prevented by forcing XSLTC to use the bootstrap
+ class loader, as illustrated below:</p>
+
+ <p><img src="class_loader.gif" alt="ClassLoader"/></p>
+ <p><ref>Figure 2: Avoiding the extensions class loader</ref></p>
+
+ <p>These are the steps that XSLTC will go through to load a class:</p>
+
+ <nl>
+ <li>the application requests an instance of the transformer factory </li>
+ <li>the Java extensions mechanism locates XSLTC as the transformer
+ factory implementation using the extensions class loader</li>
+ <li>the extensions class loader loads XSLTC</li>
+ <li>XSLTC's compiler attempts to get a reference to an external Java
+ class, but the call to Class.forName() fails, as the extensions class
+ loader does not use the user's class path</li>
+ <li>XSLTC attempts to get a reference to the bootstrap class loader, and
+ requests it to load the external class</li>
+ <li>the bootstrap class loader loads the requested class</li>
+ </nl>
+
+ <p>Step 5) is only allowed if XSLTC has special permissions. But, remember
+ that this problem only occurs when XSLTC is put in the
+ <code>$JAVA_HOME/jre/lib/ext</code> directory, where it is given all
+ permissions (by the default security file).</p>
+
+ </s4>
+
+ </s3>
+
+ <anchor name="transformer_design"/>
+ <s3 title="Transformer detailed design">
+
+ <p>The <code>Transformer</code> class is a simple proxy that passes
+ transformation settings on to its translet instance before it invokes the
+ translet's <code>doTransform()</code> method. The <code>Transformer</code>'s
+ <code>transform()</code> method maps directly to the translet's
+ <code>doTransform()</code> method.</p>
+
+ <s4 title="Transformer input and output handling">
+ <p>The <code>Transformer</code> handles its input in a manner similar to
+ that of the <code>TransformerFactory</code>. It has two methods for
+ creating standard SAX input and output handlers for its input and output
+ files:</p><source>
+ private DOMImpl getDOM(Source source, int mask);
+ private ContentHandler getOutputHandler(Result result);</source>
+
+ <p>One aspect of the <code>getDOM</code> method is that it handles four
+ various types of <code>Source</code> objects. In addition to the standard
+ DOM, SAX and stream types, it also handles an extended
+ <code>XSLTCSource</code> input type. This input type is a lightweight
+ wrapper from XSLTC's internal DOM-like input tree. This allows the user
+ to create a cache or pool of XSLTC's native input data structures
+ containing the input XML document. The <code>XSLTCSource</code> class
+ is located in:</p><source>
+ org.apache.xalan.xsltc.trax.XSLTCSource</source>
+ </s4>
+
+ <s4 title="Transformer parameter settings">
+ <p>XSLTC's native interface has get/set methods for stylesheet parameters,
+ identical to those of the TrAX API. The parameter handling methods of
+ the <code>Transformer</code> implementation are pure proxies.</p>
+ </s4>
+
+ <s4 title="Transformer output settings">
+ <p>The Transformer interface of TrAX has for methods for retrieving and
+ defining the transformation output document settings:</p><source>
+ public Properties getOutputProperties();
+ public String getOutputProperty(String name);
+ public void setOutputProperties(Properties properties);
+ public void setOutputProperty(String name, String value);</source>
+
+ <p>There are three levels of output settings. First there are the default
+ settings defined in the <link anchor="">XSLT 1.0 spec</link>, then there
+ are the settings defined in the attributes of the <xsl:output>
+ element, and finally there are the settings passed in through the TrAX
+ get/setOutputProperty() methods.</p>
+
+ <p><img src="trax_output_settings.gif" alt="Output settings"/></p>
+ <p><ref>Figure 3: Passing output settings from TrAX to the translet</ref></p>
+
+ <p>The AbstractTranslet class has a series of fields that contain the
+ default values for the output settings. The compiler/Output class will
+ compile code into the translet's constructor that updates these values
+ depending on the attributes in the <xsl:output> element. The
+ Transformer implementation keeps in instance of the java.util.Properties
+ class where it keeps all properties that are set by the
+ <code>setOutputProperty()</code> and the
+ <code>setOutputProperties()</code> methods. These settings are written to
+ the translet's output settings fields prior to initiating the
+ transformation.</p>
+
+ </s4>
+
+ <s4 title="Transformer URI resolver">
+ <p>The <code>uriResolver()</code> method of the Transformer interface is
+ used to set a locator for documents referenced by the document() function
+ in XSL. The native XSLTC API has a defined interface for a DocumentCache.
+ The functionality provided by XSLTC's internal <code>DocumentCache</code>
+ interface is somewhat complimentary to the <code>URIResolver</code>, and
+ can be used side-by-side. To acomplish this we needed to find out in which
+ ways the translet can load an external document:</p>
+
+ <p><img src="uri_resolver.gif" alt="URIResolver"/></p>
+ <p><ref>Figure 4: Using URIResolver and DocumentCache objects</ref></p>
+
+ <p>From the diagram we see that these three ways are:</p>
+ <ul>
+ <li>LoadDocument -> .xml</li>
+ <li>LoadDocument -> DocumentCache -> .xml</li>
+ <li>LoadDocument -> URIResolver -> .xml</li>
+ <li>LoadDocument -> DocumentCache -> URIResolver -> .xml</li>
+ </ul>
+
+ </s4>
+
+ </s3>
+ </s2>
</s1>
1.1 xml-xalan/java/xdocs/sources/xsltc/ast_stage1.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/ast_stage2.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/ast_stage3.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/class_loader.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/compiler_design.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/output_settings.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/overall_design.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/runtime_design.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/translet_wrapping.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/trax_output_settings.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/trax_translet_wrapping.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/uri_resolver.gif
<<Binary file>>
1.1 xml-xalan/java/xdocs/sources/xsltc/xsltc_overview.xml
Index: xsltc_overview.xml
===================================================================
<?xml version="1.0" standalone="no"?>
<!DOCTYPE s1 SYSTEM "../../style/dtd/document.dtd">
<!--
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, Lotus
* Development Corporation., http://www.lotus.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
-->
<s1 title="XSLTC stylesheet compiler overview">
<s2 title="Using the Command-Line Utility">
</s2>
</s1>
---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org