# HG changeset patch # User paulb # Date 1121784569 0 # Node ID 0dcd6eda32bea18b1ac8ccff4222b948cac45873 # Parent 8d1ae6f73f7e06226f6aeaca5a8b667b3f037b70 [project @ 2005-07-19 14:49:29 by paulb] Added a Web resource implementation document. Suggested a template filename. Added notes about selector names. Changed the name of the multiple-choice document to multiple.html. diff -r 8d1ae6f73f7e -r 0dcd6eda32be docs/Web-resource.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/Web-resource.html Tue Jul 19 14:49:29 2005 +0000 @@ -0,0 +1,126 @@ + + + + + Creating Applications: Write a Web Resource + + + + +

Creating Applications: Write a Web Resource

+

With a completed template after the design, +structure annotation and selector annotation, we may now write a Web +resource which will expose our form as a Web application, allowing +users to input information and to manipulate that information using +their Web browser. Whilst XSLForms is just a normal Python package +which can be used from many kinds of programs and environments, we +shall concentrate on using the built-in WebStack +support to build a +WebStack application around our form template.

+

XSLForms Meets WebStack

+

In the directory structure created +earlier, we now want to edit the __init__.py file and +add code which will do most of the work of the form-editing +application. Here is the start of this code:

+
#!/usr/bin/env python

"A very simple example application."

import WebStack.Generic
import XSLForms.Resources
import XSLForms.Utils
import os

# Resource classes.

class VerySimpleResource(XSLForms.Resources.XSLFormsResource):

# To be continued.
+

The above import statements just include in our application +everything that it is likely to need from WebStack, XSLForms and the +standard library. Then, we define a class inheriting from a special +XSLForms class which does some of the tedious Web application +housekeeping that we would otherwise need to do ourselves.

+

We may expand the above class definition as follows:

+
class VerySimpleResource(XSLForms.Resources.XSLFormsResource):

"A very simple resource providing a hierarchy of editable fields."

resource_dir = os.path.join(os.path.split(__file__)[0], "Resources")
encoding = "utf-8"
template_resources = {
"structure" : ("structure_template.xhtml", "structure_output.xsl")
}

def respond_to_form(self, trans, form):

"""
Respond to a request having the given transaction 'trans' and the given
'form' information.
"""

# To be continued.
+

The class is started with some attribute definitions:

+ +

The class also has a method which resembles the typical respond +method of normal WebStack +resources: the respond_to_form method is, in fact, a +special version of that method providing ready-to-use information about +the form (or forms) being edited.

+

We may now add to the above method definition by considering what +the resource needs to do when being sent a request by a user of the +application.

+

Defining the Method

+

First of all, we need to inspect the form object +to see if any form data is available. Since the data is provided +throughout XSLForms as XML documents, we call the get_documents +method on the form object:

+
        documents = form.get_documents()
+

As a result of this method, we should now have a dictionary mapping +form names to XML documents containing form data. However, it is not +guaranteed that the form data for our chosen form, structure, +even exists since a user may be visiting the resource for the first +time.

+

Therefore, we test to see if the structure +document exists, creating a new document if it did not:

+
        # Ensure the presence of a document.

if documents.has_key("structure"):
structure = documents["structure"]
else:
structure = form.new_instance("structure")
+

Now we should have a document containing the data for the form being +edited, regardless of whether any form was filled out and submitted or +whether we have created a new one for that purpose.

+

It may be the case that a user pressed a button in order to add or +remove items or subitems from the form. We must respond to such things +by examining the selector information to see which parts of the structure +document are affected:

+
        # Add and remove elements according to the selectors found.

selectors = form.get_selectors()
+

The result of get_selectors is a dictionary mapping +selector names to lists of nodes affected by each particular +selector. In the selector annotation +process, we defined selectors for the addition and removal of items and +subitems, and for convenience we pass the results for each selector to +a special function to perform the appropriate operation for us:

+
        XSLForms.Utils.remove_elements(selectors.get("remove2"))
XSLForms.Utils.add_elements(selectors.get("add2"), "subitem")
XSLForms.Utils.remove_elements(selectors.get("remove"))
XSLForms.Utils.add_elements(selectors.get("add"), "item")
+

Finally, we are ready to present the edited form data. In typical +WebStack fashion, we emit the content type of the final output along +with our chosen character encoding:

+
        # Start the response.

trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding))
+

Then, we ensure that our template is ready to use by calling the +superclass's prepare_output method with the name of +the form:

+
        # Ensure that an output stylesheet exists.

trans_xsl = self.prepare_output("structure")
+

This prepares the stylesheet whose file is named in the template_resources +attribute entry, and this stylesheet is then sent to the +superclass's send_output method as part of a list of +stylesheets (although we only use a single stylesheet in this example) +along with the form data itself:

+
        # Complete the response.

self.send_output(trans, [trans_xsl], structure)
+

At this point, the user should receive their edited form and be able +to make more modifications.

+

Further Enhancements

+

We should now have an application which can be deployed and tested +using the usual WebStack techniques. However, more advanced templates +can be designed, and we shall consider multiple-choice +fields in the next activity in the development process.

+ + diff -r 8d1ae6f73f7e -r 0dcd6eda32be docs/design.html --- a/docs/design.html Tue Jul 19 14:46:59 2005 +0000 +++ b/docs/design.html Tue Jul 19 14:49:29 2005 +0000 @@ -115,7 +115,8 @@
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Example</title>
</head>
<body>
<form action="" method="POST">

<!-- Template text between the start and the interesting part. -->

<div>
<p>
Some item: <input name="value" type="text" value="some value" />
<input name="remove" type="submit" value="Remove" />
</p>
<p>
Itself containing more items:
</p>
<p>
Sub-item: <input name="subvalue" type="text" value="some other value" />
<input name="remove2" type="submit" value="Remove" />
</p>
<p>
<input name="add2" type="submit" value="Add subitem" />
</p>
</div>
<p>
<input name="add" type="submit" value="Add item" />
</p>

<!-- Template text between the interesting part and the end. -->

</form>
</body>
</html>

Once you are happy with the design of the page, save it to the directory -created earlier, then proceed to adding +created earlier (perhaps choosing the name structure_template.xhtml), +then proceed to adding structure information in the next stage of the process.

diff -r 8d1ae6f73f7e -r 0dcd6eda32be docs/directory.html --- a/docs/directory.html Tue Jul 19 14:46:59 2005 +0000 +++ b/docs/directory.html Tue Jul 19 14:49:29 2005 +0000 @@ -1,91 +1,60 @@ - - - - - - - - - - Creating Applications: Create a Directory - - - - - + - - - - -

Creating Applications: Create a Directory

- - -

The recommended directory structure of an XSLForms application is as +

Creating Applications: Create +a Directory

+

The recommended directory +structure of an XSLForms application is as follows:

- - - +
- - - - - - - - - - - - - - + + + - - - - - - - - - + - -
Example Directory Structure
- +
Example +Directory +Structure
A top-level directory corresponding to a Python packageVerySimple
-__init__.py
A +top-level directory corresponding to a Python packageVerySimple
+__init__.py
A subdirectory containing non-code resources for the + A subdirectory +containing non-code resources for the application
- +

Resources
- -...
Resources
+...
-

For the above example, the directory structure would be created using UNIX-style commands as follows:

- - +

For the above example, the +directory structure would be created using UNIX-style commands +as follows:

mkdir VerySimple
mkdir VerySimple/Resources
touch VerySimple/__init__.py
- - -

It is in the Resources subdirectory that we will save -our template files when designing them as -part of the next activity in the application development process.

- - +

It is in the Resources +subdirectory that we will save +our template files when designing +them as +part of the next activity in the application development process.

diff -r 8d1ae6f73f7e -r 0dcd6eda32be docs/overview.html --- a/docs/overview.html Tue Jul 19 14:46:59 2005 +0000 +++ b/docs/overview.html Tue Jul 19 14:49:29 2005 +0000 @@ -1,84 +1,35 @@ - - - - - - - - - - Creating Applications: An Overview - - - - - + - - - -

Creating Applications: An Overview

- -

The following steps briefly describe how to make a new application:
- -

- -
    - -
  1. Create a directory to hold your files
  2. Design the structure of the form data
  3. - -
  4. Design a template
  5. - -
  6. Add structure to the template
  7. -
  8. Add selectors to the template
  9. - - -
  10. Prepare catalogues of multiple-choice -values
  11. - -
  12. Write a Web resource to display the form
  13. - - +
  14. Adding multiple-choice fields and values
- -

Recommendations

- -
    - -
  1. Where multiple fields exist and can be added and removed, put them inside a separate element so that the selectors can successfully identify them. Otherwise, changing element orders can result in the wrong element being selected.
  2. - -
  3. Make sure that transformations on the input document produce all the necessary elements for the output document so that the resulting page gives the user the opportunity to specify data that is missing.
  4. - -
- - diff -r 8d1ae6f73f7e -r 0dcd6eda32be docs/selectors.html --- a/docs/selectors.html Tue Jul 19 14:46:59 2005 +0000 +++ b/docs/selectors.html Tue Jul 19 14:49:29 2005 +0000 @@ -34,7 +34,7 @@ style="font-weight: bold;">remove2={template:this-position()}" type="submit" value="Remove" />
</p>
<p>
<input name="add2={template:this-position()}" type="submit" value="Add subitem" />
</p>
</div>
<p>
<input name="add={template:this-position()}" type="submit" value="Add item" />
</p>

<!-- Template text between the interesting part and the end. -->

</form>
</body>
</html> + style="font-weight: bold;" />

<!-- Template text between the interesting part and the end. -->

</form>
</body>
</html>

The Remove Buttons

Some of the attributes in the previous HTML code have been changed:

@@ -61,6 +61,9 @@ form data. This means that each button will refer to a specific subitem in the form being edited. +

We define the names of the selectors in the above cases to be remove +and remove2 respectively, since the special values +begin with these identifiers.

The Add Buttons

Some other attributes have been changed in the previous HTML code:

@@ -95,10 +98,13 @@ the form being edited, and the consequence of adding an item will be the extension of the main list of items in the form. -

Whilst many forms consist only of text fields and action buttons, -other types of data are very likely to also be used. Multiple-choice or enumerated value fields in -forms are covered in the next activity in the development We define the names of the selectors in the above cases to be add2 +and add respectively, since the special values begin with +these identifiers.

+

We should now have a template that is sufficiently complete to be +used in a real application, and the writing of the application code itself will be +investigated in the next activity in the development process.