paulb@615 | 1 | <?xml version="1.0" encoding="iso-8859-1"?> |
paulb@293 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
paulb@293 | 3 | <html xmlns="http://www.w3.org/1999/xhtml"><head> |
paulb@293 | 4 | <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type" /> |
paulb@615 | 5 | <title>Using the XSLFormsResource API</title> |
paulb@293 | 6 | <link href="styles.css" rel="stylesheet" type="text/css" /></head> |
paulb@293 | 7 | <body> |
paulb@293 | 8 | <h1>Using the XSLFormsResource API</h1> |
paulb@615 | 9 | <p>The XSLForms toolkit provides a special WebStack resource class (described in the <a href="Web-resource.html">"Creating Applications: Write a Web Resource"</a> |
paulb@615 | 10 | document), and |
paulb@615 | 11 | from this class, <code>XSLFormsResource</code>, |
paulb@293 | 12 | you can derive your own application-specific resources and use the |
paulb@293 | 13 | class's API to obtain, manipulate and present form data. Although the |
paulb@615 | 14 | supplied <a href="../apidocs/index.html">API documentation</a> provides details of the class's API, specifically in the <code><a href="../apidocs/public/XSLForms.Resources.WebResources-module.html">XSLForms.Resources.WebResources</a></code><a href="../apidocs/public/XSLForms.Resources.WebResources-module.html"></a> module, this document attempts to explain how the API is used in practice.</p><h2>Resource Structure</h2><p>The structure of a Web resource derived from <code>XSLFormsResource</code> should look like this:</p><pre>class MyResource(XSLForms.Resources.WebResources.XSLFormsResource):<br /><br /> [Resource definitions]<br /><br /> def respond_to_form(self, trans, form):<br /> [Examine the form data, see if the user has added or removed anything.]<br /> [Perform additional processing and initialise the form data.]<br /> [Produce some kind of response to show the user the updated form data.]</pre><p>Since <code>XSLFormsResource</code> builds on WebStack's resource mechanisms, we do have the transaction object, <code>trans</code>, available. However, most of the information we need to access and manipulate is generally available through the <code>form</code> object.</p><h2>Defining Resources</h2><p>Classes derived from <code>XSLFormsResource</code> |
paulb@293 | 15 | support the concept of resources which are used to produce output, |
paulb@293 | 16 | support processing and to provide access to useful information. At the |
paulb@293 | 17 | class level it is essential to define at least some of these resources |
paulb@293 | 18 | in order to make a working application.</p><h3>The Resource Directory</h3><p>Since |
paulb@293 | 19 | XSLForms relies on template files residing in the filesystem, along |
paulb@293 | 20 | with other files, we need to define where such files can be found (as |
paulb@293 | 21 | described in the <a href="directory.html">"Creating Applications: Create |
paulb@353 | 22 | a Directory"</a> document). Consequently, it is the convention that all resource classes define such information as follows:</p><pre>class ConfiguratorResource(XSLForms.Resources.WebResources.XSLFormsResource):<br /><br /> resource_dir = os.path.join(os.path.split(__file__)[0], "Resources")</pre><p>All |
paulb@293 | 23 | filenames, defined in the various resource sections (as described |
paulb@293 | 24 | below) must be stated without leading path information - in other |
paulb@615 | 25 | words, as "leafnames" rather than "pathnames". Thus, an example of |
paulb@615 | 26 | an incorrect filename would be <code>/home/paulb/templates/my_template.xhtml</code>, whereas an example of a correct filename would be just <code>my_template.xhtml</code> when correcting the incorrect example.<br /></p><h3>Character Encoding</h3><p>It |
paulb@293 | 27 | is also the convention to define the character encoding of the output |
paulb@293 | 28 | produced by an application and the way ambiguous or |
paulb@293 | 29 | insufficiently-specified input should be interpreted; this is done as |
paulb@293 | 30 | follows:</p><pre> # Continuing from above...<br /><br /> encoding = "utf-8"</pre><h3>Template Resources</h3><p>The |
paulb@293 | 31 | main purpose of XSLForms is to produce Web page output containing a |
paulb@293 | 32 | visual representation of a form. Therefore, we need to define templates |
paulb@298 | 33 | (as described in the <a href="design.html">"Creating Applications: Design a Template"</a> |
paulb@298 | 34 | document) to express the representation of each kind of form, along |
paulb@615 | 35 | with any intermediate files that may be produced. A special |
paulb@615 | 36 | class-level <code>template_resources</code> dictionary is used to hold such definitions.</p><p>To |
paulb@293 | 37 | define a template resource, we first choose a name (which need not have |
paulb@615 | 38 | any special significance); we then associate with that name a |
paulb@615 | 39 | template filename and an output filename. Finally, we make an |
paulb@293 | 40 | entry for the name and its associated details in the special |
paulb@615 | 41 | class-level <code>template_resources</code> dictionary as follows:</p><pre> # Continuing from above...<br /><br /> template_resources = {<br /> "configuration" : ("config_template.xhtml", "config_output.xsl"),<br /> # More entries go here...<br /> }</pre><p>The purpose |
paulb@293 | 42 | of the output filename is to define where the intermediate |
paulb@293 | 43 | output-producing stylesheet is to be written, since the template itself |
paulb@293 | 44 | is not actually used to produce output, but knowing where the |
paulb@293 | 45 | intermediate stylesheet can be found is sometimes useful when debugging |
paulb@293 | 46 | templates and is thus defined explicitly to avoid confusion.</p><h3>Initialisation Resources</h3><p>The |
paulb@293 | 47 | XSLForms toolkit also support the initialisation of form data |
paulb@293 | 48 | documents. This document initialisation is useful when preparing a |
paulb@293 | 49 | document for output since some parts of a template may not be produced |
paulb@293 | 50 | unless certain elements are present in the form data document. For |
paulb@293 | 51 | example, a template may contain something like this:</p><pre><div template:element="hard-disks"><br /> <input template:selector-field="add-hard-disk,hard-disk" type="submit" name="..." value="Add hard disk"/><br /> <p template:element="hard-disk"><br /> ...<br /> </p><br /></div></pre><p>In the above example, if no <code>hard-disks</code> element exists, the selector will not be displayed and there will be no way of adding <code>hard-disk</code> elements. With document initialisation, certain measures can be taken to ensure that the <code>hard-disks</code> element is added before output is generated.</p><p>At the class level, the <code>init_resources</code> |
paulb@293 | 52 | dictionary is used to hold definitions mapping initialiser names (which |
paulb@293 | 53 | need not have any special significance) to the initialiser details: the |
paulb@293 | 54 | filename of the template which defines the structure of the form data, |
paulb@293 | 55 | and an intermediate filename similar to the output filename described |
paulb@293 | 56 | in the context of template resources above. An example of this is as |
paulb@293 | 57 | follows:</p><pre> # Continuing from above...<br /><br /> init_resources = {<br /> "configuration" : ("config_template.xhtml", "config_input.xsl"),<br /> # More entries go here...<br /> }</pre><p>Note |
paulb@293 | 58 | that initialiser and template resources may (and should) share the same |
paulb@293 | 59 | template filename. As with the output filename for template resources, |
paulb@293 | 60 | the input filename provides firm information about the location of the |
paulb@293 | 61 | stylesheet which actually performs the initialisation process.</p><h3>Document Resources</h3><p>Since |
paulb@293 | 62 | it is the XSLForms convention to access files using a simple name, any |
paulb@615 | 63 | other document resources should be defined in the <code>document_resources</code> |
paulb@293 | 64 | dictionary at the class level. Such document resources may be used in |
paulb@293 | 65 | the initialisation process or in other transformations (as described |
paulb@293 | 66 | below), and are defined as entries mapping names to filenames such as |
paulb@293 | 67 | in the following example:</p><pre> # Continuing from above...<br /><br /> document_resources = {<br /> "accessories" : "config_accessories.xml",<br /> "base-system" : "config_base_system.xml",<br /> # More entries go here...<br /> }</pre><p>There is no particular limitation on the types of files which can be referenced in the <code>document_resources</code> |
paulb@293 | 68 | dictionary, nor any insistence in the XSLForms toolkit to define such |
paulb@293 | 69 | files as resources - the dictionary is merely a convenience for |
paulb@615 | 70 | accessing files in the resources directory.</p><h3>Transform Resources</h3><p>It is sometimes the case that initialisation of a document |
paulb@293 | 71 | is not sufficient and that additional processing needs to be done. |
paulb@293 | 72 | Whilst various techniques exist for the processing of XML-based |
paulb@293 | 73 | information, since XSLForms is part of a wider toolkit based on XSL |
paulb@293 | 74 | transformations, it seems reasonable to provide certain facilities for |
paulb@293 | 75 | the usage of such transformations. Thus, stylesheet processing |
paulb@615 | 76 | pipelines may be defined at the class level in the <code>transform_resources</code> dictionary.</p><p>Entries in the <code>transform_resources</code> |
paulb@293 | 77 | dictionary map simple names (which need not have any special |
paulb@293 | 78 | significance) to collections of stylesheet filenames as in the |
paulb@293 | 79 | following example:</p><pre> # Continuing from above...<br /><br /> transform_resources = {<br /> "filter" : ["filter.xsl"],<br /> # More entries go here...<br /> }</pre><p>Where |
paulb@293 | 80 | more than one stylesheet filename is specified, the stylesheets are |
paulb@293 | 81 | applied from first to last in the transformation. Additional |
paulb@293 | 82 | information, such as stylesheet parameters and referenced documents, |
paulb@293 | 83 | are mentioned when the transformation is acquired and invoked, as |
paulb@293 | 84 | described below.</p><h3>In-Page Update Resources</h3><p>In certain |
paulb@293 | 85 | applications, a technique referred to within XSLForms as "in-page |
paulb@293 | 86 | updates" is employed to provide updates of details within a Web page |
paulb@293 | 87 | without refreshing the entire page itself (and this is described in the |
paulb@293 | 88 | <a href="in-page-updates.html">"Creating Applications: In-Page Updates"</a> |
paulb@293 | 89 | document). When such updates are requested, applications have to |
paulb@293 | 90 | identify the kind of update requested and then to select the correct |
paulb@293 | 91 | part of the Web page to generate as output. Consequently, the |
paulb@293 | 92 | application has to have some kind of record of the different kinds of |
paulb@293 | 93 | updates and the corresponding parts of the whole page template to use, |
paulb@615 | 94 | and this information is recorded in the class-level <code>in_page_resources</code> dictionary.</p><p>The form of an entry in the <code>in_page_resources</code> |
paulb@293 | 95 | dictionary is that of a mapping from a name identifying the kind of |
paulb@293 | 96 | update to the details of the part of the template to be employed in |
paulb@293 | 97 | producing the final output for the update: an intermediate filename |
paulb@293 | 98 | (distinct from that associated with the whole page template), and a |
paulb@293 | 99 | node identifier used to isolate the pertinent part of the whole page |
paulb@293 | 100 | template. Here is an example of an in-page resource definition:</p><pre> # Continuing from above...<br /><br /> in_page_resources = {<br /> "cpu" : ("config_output_cpu.xsl", "cpu-node"),<br /> # More entries go here...<br /> }</pre><h4>Update Names</h4><p>It |
paulb@293 | 101 | is important to note that, unlike other resources, the name identifying |
paulb@293 | 102 | the kind of update is significant: consider an application available at |
paulb@615 | 103 | the following location:</p><pre>http://localhost/configurator/</pre><p>An in-page update called <code>cpu</code> would be accessed through the following location:</p><pre>http://localhost/configurator/cpu</pre><p>Thus, |
paulb@293 | 104 | the availability of such an update "service" depends on the proper |
paulb@293 | 105 | configuration of the Web application to let such updates be handled by |
paulb@293 | 106 | the resource.</p><h4>Update Nodes</h4><p>The node identifier mentioned |
paulb@293 | 107 | in an in-page update resource definition must be a valid node |
paulb@293 | 108 | identifier in the whole page template document. Thus, if we wished to |
paulb@615 | 109 | use the identifier in the above example together with <code>config_template.xhtml</code>, we would have to ensure that the identifier appeared as a value of an <code>id</code> |
paulb@293 | 110 | node in that template document. Note that the choice of template |
paulb@293 | 111 | document is not defined here, but is instead made when handling an |
paulb@615 | 112 | in-page update request.</p><h2>Examining the Form Data</h2><p>The form data is available through the <code>form</code> object which exposes the <code><a href="../apidocs/public/XSLForms.Fields.Form-class.html">XSLForms.Fields.Form</a></code> API. The most interesting operations are as follows:</p><h3>Obtain the Form Data Documents</h3><p>Since |
paulb@293 | 113 | XSLForms is an XML-based toolkit, the form data is available as XML |
paulb@293 | 114 | documents which can be accessed and manipulated using a DOM-style API. |
paulb@293 | 115 | Upon receiving submitted form data, XSLForms converts the data to such |
paulb@293 | 116 | documents and then makes it available through the <code>form</code> |
paulb@293 | 117 | object by associating certain document names with the actual documents |
paulb@293 | 118 | themselves in a dictionary; this dictionary can be obtained as follows:</p><pre>documents = form.get_documents()</pre><p>Imagine that a template document has been written with <code>items</code> as the root (or topmost) element; such a document will consequently be made available via the <code>form</code> object's documents dictionary using the name <code>items</code>, and can be accessed as follows:</p><pre>items = documents["items"]</pre><p>However, |
paulb@293 | 119 | it may be the case that no form data has been submitted. To avoid |
paulb@293 | 120 | causing an exception, we should really test for the presence of such a |
paulb@293 | 121 | document first:</p><pre>if documents.has_key("items"):<br /> items = documents["items"]</pre><p>Since |
paulb@293 | 122 | it is likely that we will want to work with such a document regardless |
paulb@293 | 123 | of whether one existed before - we must after all prepare such a |
paulb@293 | 124 | document in the first place in order to show it to the user and have it |
paulb@615 | 125 | submitted back to us - we really want to create it if it does not exist:</p><pre>if documents.has_key("items"):<br /> items = documents["items"]<br />else:<br /> items = form.new_document("items")</pre><p>The resulting <code>items</code> object is a genuine DOM-style document containing the form data.</p><h3>Obtain the Form Data Selectors</h3><p>As described in the <a href="selectors.html">"Creating Applications: Add Selectors"</a> |
paulb@293 | 126 | document, XSLForms templates may define selectors - special form fields |
paulb@293 | 127 | which select parts of the form data documents and make those parts |
paulb@293 | 128 | available to applications; such selector information can be obtained as |
paulb@615 | 129 | follows:</p><pre>selectors = form.get_selectors()</pre><p>If a selector was defined with the name <code>remove</code>, then any selected elements that are associated with this selector may be obtained as follows:</p><pre>removed_elements = selectors.get("remove") # which will return None if no such selector was defined</pre><p>Since |
paulb@293 | 130 | the collection contains DOM-style elements, various XML libraries and |
paulb@293 | 131 | tools may be used to manipulate the data. However, XSLForms also |
paulb@293 | 132 | provides convenience functions to add and remove elements.</p><h3>Obtaining Other Parameters</h3><p>Sometimes, |
paulb@293 | 133 | there is a need to obtain the "raw" request parameters submitted by the |
paulb@293 | 134 | Web client or browser which sent the form data in to the application. |
paulb@615 | 135 | Such parameters could be obtained using the <code>trans</code> object, but it is also possible to use the following approach:</p><pre>parameters = form.get_parameters()<br />some_parameter = parameters.get("something") # which returns None if no such parameter exists; a list otherwise<br />another_parameter = parameters.get("another", [""])[0] # which will always return a string, empty if no such parameter was found</pre><h2>Performing Additional Processing</h2><p>Additional |
paulb@298 | 136 | processing of the form data can be performed in many different ways, |
paulb@298 | 137 | limited only by the DOM-style API exposed by the data and the XSL |
paulb@615 | 138 | transformation features available in the XSLForms toolkit.</p><h3>Transformations</h3><p>To take advantage of the defined <code>transform_resources</code>, we can call a method on the resource itself to prepare such resources:</p><pre>filter_stylesheets = self.prepare_transform("filter")</pre><p>Then, |
paulb@293 | 139 | with the result of this call (a list of stylesheet filenames), we can |
paulb@293 | 140 | then perform a transformation on a document, producing a new document |
paulb@615 | 141 | from the results:</p><pre>configuration_document = self.get_result(filter_stylesheets, configuration_document)</pre><p>This new document is different from the document supplied to the <code>get_result</code> |
paulb@293 | 142 | method. It should therefore be noted that any references to elements in |
paulb@293 | 143 | the old document will not affect the new document; thus selectors |
paulb@615 | 144 | previously obtained from the <code>form</code> object will not refer to elements in the new document. However, by setting the new document in the <code>form</code> object, new selectors may be obtained referring to elements in the new document:</p><pre>form.set_document("configuration", configuration_document)<br />selectors = form.get_selectors()</pre><p>Care |
paulb@293 | 145 | must be taken doing this, however, since the selectors may now not |
paulb@293 | 146 | refer to valid elements - the transformation may have removed or moved |
paulb@615 | 147 | elements previously referred to by the selectors.</p><p>The <code>get_result</code> |
paulb@293 | 148 | method also supports stylesheet parameters, document references and |
paulb@293 | 149 | stylesheet expressions; these are described in the "Additional |
paulb@298 | 150 | Stylesheet Parameters" section below.</p><h3>Using Selectors to Modify the Data</h3><p>As |
paulb@298 | 151 | described above in "Obtain the Form Data Selectors", if the user of an |
paulb@298 | 152 | application requested changes to the form data using a selector field |
paulb@298 | 153 | (typically represented by a button or checkbox in a Web page), a list |
paulb@615 | 154 | of selected elements will be available to the resource through the <code>form</code> object. Given a selector which is associated with a <code>remove</code> |
paulb@298 | 155 | operation, we could use the DOM-style API exposed by the contents of |
paulb@298 | 156 | the selectors to perform such an operation in the resource using our |
paulb@298 | 157 | own code. However, the XSLForms toolkit provides some useful |
paulb@615 | 158 | convenience functions to assist in the removal or addition of elements:</p><pre># After doing this:<br /># import XSLForms.Utils<br /><br /># Removing elements...<br /><br />removed_elements = selectors.get("remove") # this may return None<br />XSLForms.Utils.remove_elements(removed_elements) # this can handle None, realising that no elements are to be removed<br /><br /># Adding elements...<br /><br />places_to_add_elements = selectors.get("add")<br />XSLForms.Utils.add_elements(places_to_add_elements, "element")</pre><p>See the <code><a href="../apidocs/public/XSLForms.Utils-module.html">XSLForms.Utils</a></code><a href="../apidocs/public/XSLForms.Utils-module.html"></a> documentation for more information on these functions.<br /></p><h2>Document Initialisation</h2><p>The initialisation of a document, using information defined in the <code>init_resources</code> |
paulb@293 | 159 | attribute, is similar to the transformation of a document as described |
paulb@293 | 160 | above. First, we obtain a reference to an initialisation stylesheet:</p><pre>init_stylesheet = self.prepare_initialiser("configuration")</pre><p>Note |
paulb@293 | 161 | that only a single stylesheet is returned. With the result of the call, |
paulb@293 | 162 | we then perform a transformation similar to the above activity, |
paulb@293 | 163 | although we have to supply the returned stylesheet in a list to be |
paulb@615 | 164 | compatible with the <code>get_result</code> method:</p><pre>configuration_document = self.get_result([init_stylesheet], configuration_document)</pre><p>In practice, the above call will probably not suffice: if <a href="multiple.html">multiple-choice fields</a> |
paulb@293 | 165 | are used in the template, there will be a need to initialise such |
paulb@293 | 166 | elements using references to other documents containing the values of |
paulb@293 | 167 | such fields; for example:</p><pre>configuration_document = self.get_result([init_stylesheet], configuration_document,<br /> references={<br /> "cpu" : self.prepare_document("cpu")<br /> })</pre><p>The |
paulb@293 | 168 | use of document references and other stylesheet parameter information |
paulb@293 | 169 | is described in the "Additional Stylesheet Parameters" section below.</p><h2>Preparing Responses</h2><p>The process of preparing a response involves three main steps:</p><ol><li>Setting a content type.</li><li>Defining an output stylesheet and parameter information.</li><li>Sending the output to the user.</li></ol><h3>Setting a Content Type</h3><p>In |
paulb@293 | 170 | the examples supplied with XSLTools, the content type is generally |
paulb@293 | 171 | defined as that of XHTML, meaning that the resulting output should be |
paulb@293 | 172 | accessible to most modern Web browsers. When writing resources based |
paulb@615 | 173 | on <code>XSLFormsResource</code>, we can just use the WebStack API to set the content type:</p><pre>trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding))</pre><p>Note that the <code>encoding</code> attribute is used here to make the character encoding clear to the user's Web browser or client.</p><h3>Defining an Output Stylesheet</h3><p>In most cases, the output stylesheet can be chosen by selecting a template name and invoking a method on the resource:</p><pre>output_stylesheet = self.prepare_output("configuration")</pre><p>However, |
paulb@293 | 174 | where in-page updates are handled, we may need to check to see if we |
paulb@293 | 175 | should be sending a fragment of the whole page instead. First, we must |
paulb@615 | 176 | check to see if an in-page update is being requested:</p><pre>in_page_resource = self.get_in_page_resource(trans)</pre><p>The |
paulb@293 | 177 | result of calling the above method should be a string identifying an |
paulb@293 | 178 | "in-page resource" - that is, a kind of in-page update related to part |
paulb@615 | 179 | of the whole page - if such a "resource" is actually being |
paulb@293 | 180 | requested. We can thus check to see if such a request is taking place:</p><pre>if in_page_resource in self.in_page_resources.keys():<br /> [Handle the in-page update request]</pre><p>If |
paulb@293 | 181 | so, instead of getting a stylesheet which produces output for the whole |
paulb@293 | 182 | page, we get a "fragment" which produces output only for the part of |
paulb@293 | 183 | the page being updated:</p><pre> # Continued from above...<br /><br /> output_stylesheet = self.prepare_fragment("configuration", in_page_resource)<br /> stylesheet_parameters = self.prepare_parameters(parameters) # from form.get_parameters()</pre><p>An |
paulb@293 | 184 | additional step when handling in-page updates is the usage of |
paulb@293 | 185 | stylesheet parameters to send in some required information about the |
paulb@615 | 186 | location of the update in the page. The <code>prepare_parameters</code> |
paulb@293 | 187 | method on the resource is used to discover this information and return |
paulb@293 | 188 | it as a dictionary to be passed to the final output generation activity.</p><h3>Sending the Output to the User</h3><p>Given |
paulb@293 | 189 | an output stylesheet reference and possibly some parameters, the output |
paulb@293 | 190 | is sent to the user with a single call to a method on the resource |
paulb@615 | 191 | object:</p><pre>self.send_output(trans, [output_stylesheet], configuration_document, stylesheet_parameters)</pre><p>This method should, using the <code>encoding</code> |
paulb@293 | 192 | attribute on the resource class, ensure that the generated output is |
paulb@615 | 193 | correct and consistent for the user's Web browser or client.</p><h2>Additional Stylesheet Parameters</h2><p>In addition to a collection of stylesheets and a document to process, the <code>get_result</code> and <code>send_output</code> methods can accept a number of possible sources of information:</p><ul><li>Stylesheet parameters</li><li>Document references</li><li>Stylesheet expressions</li></ul><p>Generally, |
paulb@293 | 194 | stylesheet parameters are used to configure the output in some way, |
paulb@293 | 195 | whilst document references and stylesheet expressions typically offer a |
paulb@293 | 196 | means of accessing additional information that is to be merged in or |
paulb@293 | 197 | included in the processed document. The most common need to introduce |
paulb@293 | 198 | additional information arises from the use of multiple-choice elements; |
paulb@293 | 199 | consider the list of values given in the <a href="multiple.html">"Creating Applications: Adding Multiple-Choice Fields and Values"</a> document:</p><pre><?xml version="1.0"?><br /><type><br /> <type-enum value="(Not selected)"/><br /> <type-enum value="Important"/><br /> <type-enum value="Not important"/><br /> <type-enum value="Personal"/><br /></type></pre><p>Such |
paulb@293 | 200 | information needs to reside somewhere and then be referenced in order |
paulb@293 | 201 | to be included in the processing operation being performed, which would |
paulb@615 | 202 | either be a document initialisation or just a normal transformation.</p><h3>Document References</h3><p>To refer to an externally-defined information, we define the document resource as described above:</p><pre> # At class attribute level...<br /><br /> document_resources = {<br /> "types" : "types.xml",<br /> # Other documents...<br /> }</pre><p>Then, we access the resource, getting a reference to the document:</p><pre>types_xml = self.prepare_document("types")</pre><p>To bring this document into the processing operation, we add an entry to a dictionary passed as the <code>references</code> parameter to <code>get_result</code> (or <code>send_output</code>, if appropriate). In the above example, the information is referenced as follows in the template document:</p><pre> <select template:multiple-choice-field="type,value" name="..."><br /> <option template:multiple-choice-value="type-enum,value,selected" value="..." /><br /> </select></pre><p>Therefore, we take the element name, <code>type</code>, from the field and use it to refer to the external document in the dictionary of references:</p><pre>structure = self.get_result([structure_xsl], structure, references={"type" : types_xml})</pre><p>This should result in the stylesheet incorporating the information from the types document into the transformation.</p><h3>Stylesheet Expressions</h3><p>In |
paulb@293 | 203 | more advanced cases, referencing external documents does not provide |
paulb@293 | 204 | enough flexibility when introducing additional information into a |
paulb@293 | 205 | transformation. An alternative approach involves copying data into the |
paulb@293 | 206 | document to be processed and then to supply references to the data in |
paulb@353 | 207 | its new location within the document.</p></body></html> |