1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/docs/Web-resource.html Tue Jul 19 14:49:29 2005 +0000
1.3 @@ -0,0 +1,126 @@
1.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1.5 +<html xmlns="http://www.w3.org/1999/xhtml">
1.6 +<head>
1.7 + <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type" />
1.8 + <title>Creating Applications: Write a Web Resource</title>
1.9 + <meta name="generator"
1.10 + content="amaya 8.1a, see http://www.w3.org/Amaya/" />
1.11 + <link href="styles.css" rel="stylesheet" type="text/css" />
1.12 +</head>
1.13 +<body>
1.14 +<h1>Creating Applications: Write a Web Resource</h1>
1.15 +<p>With a completed template after the <a href="design.html">design</a>,
1.16 +<a href="structure.html">structure annotation</a> and <a
1.17 + href="selectors.html">selector annotation</a>, we may now write a Web
1.18 +resource which will expose our form as a Web application, allowing
1.19 +users to input information and to manipulate that information using
1.20 +their Web browser. Whilst XSLForms is just a normal Python package
1.21 +which can be used from many kinds of programs and environments, we
1.22 +shall concentrate on using the built-in <a
1.23 + href="http://www.boddie.org.uk/python/WebStack.html">WebStack</a>
1.24 +support to build a
1.25 +WebStack application around our form template.</p>
1.26 +<h2>XSLForms Meets WebStack </h2>
1.27 +<p>In the <a href="directory.html">directory structure</a> created
1.28 +earlier, we now want to edit the <code>__init__.py</code> file and
1.29 +add code which will do most of the work of the form-editing
1.30 +application. Here is the start of this code:</p>
1.31 +<pre>#!/usr/bin/env python<br /><br />"A very simple example application."<br /><br />import WebStack.Generic<br />import XSLForms.Resources<br />import XSLForms.Utils<br />import os<br /><br /># Resource classes.<br /><br />class VerySimpleResource(XSLForms.Resources.XSLFormsResource):<br /><br /> # To be continued.</pre>
1.32 +<p>The above import statements just include in our application
1.33 +everything that it is likely to need from WebStack, XSLForms and the
1.34 +standard library. Then, we define a class inheriting from a special
1.35 +XSLForms class which does some of the tedious Web application
1.36 +housekeeping that we would otherwise need to do ourselves.</p>
1.37 +<p>We may expand the above class definition as follows:</p>
1.38 +<pre>class VerySimpleResource(XSLForms.Resources.XSLFormsResource):<br /><br /> "A very simple resource providing a hierarchy of editable fields."<br /><br /> resource_dir = os.path.join(os.path.split(__file__)[0], "Resources")<br /> encoding = "utf-8"<br /> template_resources = {<br /> "structure" : ("structure_template.xhtml", "structure_output.xsl")<br /> }<br /><br /> def respond_to_form(self, trans, form):<br /><br /> """<br /> Respond to a request having the given transaction 'trans' and the given<br /> 'form' information.<br /> """<br /><br /> # To be continued.</pre>
1.39 +<p>The class is started with some attribute definitions:</p>
1.40 +<ul>
1.41 + <li>The <code>resource_dir</code> attribute is used to locate
1.42 +the template, stylesheet and other non-Python resources. We calculate
1.43 +this attribute by taking the location of the Python package itself and
1.44 +finding the <code>Resources</code> subdirectory, just as described
1.45 +in the <a href="directory.html">directory structure</a> document.</li>
1.46 + <li>The <code>encoding</code> attribute is not strictly
1.47 +necessary, but it states which character encoding will be used in the
1.48 +Web pages generated by the template, and UTF-8 is a safe choice in most
1.49 +situations.</li>
1.50 + <li>The <code>template_resources</code> attribute is a
1.51 +dictionary mapping a name onto details about our template and the
1.52 +stylesheet that will actually produce the Web pages for each form being
1.53 +edited.<br />
1.54 + <ol>
1.55 + <li>For the key, we choose a name that can easily be remembered
1.56 +and associated with our template: <code>structure</code> (since
1.57 +the root element of the form data is always <code>structure</code>)</li>
1.58 + <li>Then, we specify the filename of our template in the <code>Resources</code>
1.59 +directory: <code>structure_template.xhtml</code> (if the suggested
1.60 +name was used)</li>
1.61 + <li>Finally, we choose a filename for the stylesheet. Since this
1.62 +is automatically produced from the template, we only need to choose a
1.63 +name which is not already in use by another file, and for clarity a
1.64 +name similar to that of the template is recommended: <code>structure_output.xsl</code></li>
1.65 + </ol>
1.66 + </li>
1.67 +</ul>
1.68 +<p>The class also has a method which resembles the typical <code>respond</code>
1.69 +method of normal <a
1.70 + href="http://www.boddie.org.uk/python/WebStack.html">WebStack</a>
1.71 +resources: the <code>respond_to_form</code> method is, in fact, a
1.72 +special version of that method providing ready-to-use information about
1.73 +the form (or forms) being edited.</p>
1.74 +<p>We may now add to the above method definition by considering what
1.75 +the resource needs to do when being sent a request by a user of the
1.76 +application.</p>
1.77 +<h3>Defining the Method</h3>
1.78 +<p>First of all, we need to inspect the <code>form</code> object
1.79 +to see if any form data is available. Since the data is provided
1.80 +throughout XSLForms as XML documents, we call the <code>get_documents</code>
1.81 +method on the <code>form</code> object:</p>
1.82 +<pre> documents = form.get_documents()</pre>
1.83 +<p>As a result of this method, we should now have a dictionary mapping
1.84 +form names to XML documents containing form data. However, it is not
1.85 +guaranteed that the form data for our chosen form, <code>structure</code>,
1.86 +even exists since a user may be visiting the resource for the first
1.87 +time.</p>
1.88 +<p>Therefore, we test to see if the <code>structure</code>
1.89 +document exists, creating a new document if it did not:</p>
1.90 +<pre> # Ensure the presence of a document.<br /><br /> if documents.has_key("structure"):<br /> structure = documents["structure"]<br /> else:<br /> structure = form.new_instance("structure")<br /></pre>
1.91 +<p>Now we should have a document containing the data for the form being
1.92 +edited, regardless of whether any form was filled out and submitted or
1.93 +whether we have created a new one for that purpose.</p>
1.94 +<p>It may be the case that a user pressed a button in order to add or
1.95 +remove items or subitems from the form. We must respond to such things
1.96 +by examining the selector information to see which parts of the <code>structure</code>
1.97 +document are affected:</p>
1.98 +<pre> # Add and remove elements according to the selectors found.<br /><br /> selectors = form.get_selectors()<br /></pre>
1.99 +<p>The result of <code>get_selectors</code> is a dictionary mapping
1.100 +selector names to lists of nodes affected by each particular
1.101 +selector. In the <a href="selectors.html">selector annotation</a>
1.102 +process, we defined selectors for the addition and removal of items and
1.103 +subitems, and for convenience we pass the results for each selector to
1.104 +a special function to perform the appropriate operation for us:</p>
1.105 +<pre> XSLForms.Utils.remove_elements(selectors.get("remove2"))<br /> XSLForms.Utils.add_elements(selectors.get("add2"), "subitem")<br /> XSLForms.Utils.remove_elements(selectors.get("remove"))<br /> XSLForms.Utils.add_elements(selectors.get("add"), "item")<br /></pre>
1.106 +<p>Finally, we are ready to present the edited form data. In typical
1.107 +WebStack fashion, we emit the content type of the final output along
1.108 +with our chosen character encoding:</p>
1.109 +<pre> # Start the response.<br /><br /> trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding))<br /></pre>
1.110 +<p>Then, we ensure that our template is ready to use by calling the
1.111 +superclass's <code>prepare_output</code> method with the name of
1.112 +the form:</p>
1.113 +<pre> # Ensure that an output stylesheet exists.<br /><br /> trans_xsl = self.prepare_output("structure")<br /></pre>
1.114 +<p>This prepares the stylesheet whose file is named in the <code>template_resources</code>
1.115 +attribute entry, and this stylesheet is then sent to the
1.116 +superclass's <code>send_output</code> method as part of a list of
1.117 +stylesheets (although we only use a single stylesheet in this example)
1.118 +along with the form data itself:</p>
1.119 +<pre> # Complete the response.<br /><br /> self.send_output(trans, [trans_xsl], structure)</pre>
1.120 +<p>At this point, the user should receive their edited form and be able
1.121 +to make more modifications.</p>
1.122 +<h2>Further Enhancements</h2>
1.123 +<p>We should now have an application which can be deployed and tested
1.124 +using the usual WebStack techniques. However, more advanced templates
1.125 +can be designed, and we shall consider <a href="multiple.html">multiple-choice
1.126 +fields</a> in the next activity in the development <a
1.127 + href="overview.html">process</a>.</p>
1.128 +</body>
1.129 +</html>