paulb@104 | 1 | Introduction
|
paulb@104 | 2 | ------------
|
paulb@76 | 3 |
|
paulb@104 | 4 | XSLTools is a collection of modules and packages facilitating the development
|
paulb@104 | 5 | of applications based on XML, XSL stylesheets and transformations, notably Web
|
paulb@104 | 6 | applications involving complicated Web forms potentially consisting of
|
paulb@104 | 7 | editable hierarchical structures and potentially involving "live" or "in-page"
|
paulb@104 | 8 | dynamic updates to portions of those Web forms.
|
paulb@28 | 9 |
|
paulb@109 | 10 | Quick Start
|
paulb@109 | 11 | -----------
|
paulb@109 | 12 |
|
paulb@109 | 13 | Try running the demo:
|
paulb@109 | 14 |
|
paulb@109 | 15 | python tools/demo.py
|
paulb@109 | 16 |
|
paulb@109 | 17 | An introductory guide to creating applications can be found in the docs
|
paulb@109 | 18 | directory - see docs/index.html for the start page.
|
paulb@109 | 19 |
|
paulb@109 | 20 | Contact, Copyright and Licence Information
|
paulb@109 | 21 | ------------------------------------------
|
paulb@109 | 22 |
|
paulb@109 | 23 | The current Web page for XSLTools at the time of release is:
|
paulb@109 | 24 |
|
paulb@109 | 25 | http://www.boddie.org.uk/python/XSLTools.html
|
paulb@109 | 26 |
|
paulb@109 | 27 | Copyright and licence information can be found in the docs directory - see
|
paulb@194 | 28 | docs/COPYING.txt, docs/LICENCE.txt and docs/LICENCE-Sarissa.txt for more
|
paulb@194 | 29 | information.
|
paulb@109 | 30 |
|
paulb@104 | 31 | Dependencies
|
paulb@104 | 32 | ------------
|
paulb@104 | 33 |
|
paulb@104 | 34 | XSLTools has the following basic dependencies:
|
paulb@28 | 35 |
|
paulb@104 | 36 | Package Release Information
|
paulb@104 | 37 | ------- -------------------
|
paulb@104 | 38 |
|
paulb@207 | 39 | libxml2dom 0.2.1
|
paulb@185 | 40 | libxml2 Tested with 2.6.17
|
paulb@185 | 41 | libxslt Tested with 1.1.12
|
paulb@28 | 42 |
|
paulb@210 | 43 | The example Web applications require WebStack (release 1.0 or later).
|
paulb@329 | 44 | The example PyQt applications have been tested with PyQt 3.15.
|
paulb@104 | 45 |
|
paulb@190 | 46 | New in XSLTools 0.2 (Changes since XSLTools 0.1)
|
paulb@190 | 47 | ------------------------------------------------
|
paulb@190 | 48 |
|
paulb@231 | 49 | * Made a new XSLTools package and moved XSLOutput into it.
|
paulb@252 | 50 | * Improved serialisation of transformation results so that output options
|
paulb@252 | 51 | are observed (in some cases, at least).
|
paulb@252 | 52 | * Fixed stylesheet and reference document paths so that libxslt should not
|
paulb@252 | 53 | now become confused by ambiguous relative paths.
|
paulb@286 | 54 | * Added expression parameters to XSLOutput.Processor so that in-document
|
paulb@286 | 55 | data can be used to, for example, initialise multiple-choice field values.
|
paulb@252 | 56 | * Added input/initialiser support so that input documents can be tidied or
|
paulb@252 | 57 | initialised using information from the template.
|
paulb@286 | 58 | * Added template:init for use with template:element in XSLForms to control
|
paulb@286 | 59 | element initialisation where necessary.
|
paulb@252 | 60 | * Added special high-level "macro" attributes (eg. template:attribute-field)
|
paulb@252 | 61 | which should make templates easier to write and maintain.
|
paulb@286 | 62 | * Added template:if to XSLForms, providing conditional output of annotated
|
paulb@286 | 63 | elements.
|
paulb@290 | 64 | * Added set_document to XSLForms.Fields.Form.
|
paulb@297 | 65 | * Added prepare_parameters to XSLForms.Resources.XSLFormsResource.
|
paulb@286 | 66 | * Added element-path and url-encode XSLForms extension functions.
|
paulb@286 | 67 | * Improved Unicode support in the XSLForms extension functions.
|
paulb@231 | 68 | * Changed in-page requests to contain proper POST data.
|
paulb@252 | 69 | * Updated the code to work with WebStack 1.0 changes and adopted the
|
paulb@252 | 70 | new-style WebStack demonstration mechanism.
|
paulb@286 | 71 | * Added XMLCalendar and XMLTable (to the XSLTools package).
|
paulb@231 | 72 | * Added a dictionary (or word lookup) example application.
|
paulb@286 | 73 | * Added a job candidate profile (or CV editor) example application.
|
paulb@297 | 74 | * Added a template attribute reference and an XSLFormsResource guide to the
|
paulb@297 | 75 | documentation.
|
paulb@231 | 76 | * Added Debian package support.
|
paulb@231 | 77 | * Added missing COPYING.txt file.
|
paulb@231 | 78 | * Renamed the scripts to avoid naming issues in system-wide installations.
|
paulb@329 | 79 | * Added a PyQt example based on the system configurator example, with the
|
paulb@329 | 80 | form prepared in Qt Designer.
|
paulb@190 | 81 |
|
paulb@104 | 82 | Notes on In-Page Update Functionality
|
paulb@104 | 83 | -------------------------------------
|
paulb@28 | 84 |
|
paulb@185 | 85 | Special note #1: Konqueror seems in certain cases to remember replaced form
|
paulb@185 | 86 | content (when replaceChild is used to replace regions of the page which
|
paulb@185 | 87 | include form elements). This causes the browser to believe that more form
|
paulb@185 | 88 | fields exist on the page than actually do so, and subsequent form submissions
|
paulb@185 | 89 | thus include the values of such removed fields. A special hack is in place to
|
paulb@185 | 90 | disable form fields by changing their names, thus causing Konqueror to not
|
paulb@185 | 91 | associate such fields with the real, active fields; this hack does not seem to
|
paulb@185 | 92 | cause problems for Mozilla. This needs some investigation to determine in
|
paulb@185 | 93 | exactly which circumstances the problem arises.
|
paulb@185 | 94 |
|
paulb@185 | 95 | Special note #2: Konqueror also seems to crash if asked to find elements using
|
paulb@185 | 96 | an empty 'id' attribute string. This needs some investigation to see if it
|
paulb@185 | 97 | really is the getElementById call that causes the crash.
|
paulb@125 | 98 |
|
paulb@221 | 99 | Special note #3: Konqueror's XMLHttpRequest seems to append null characters to
|
paulb@221 | 100 | the end of field values. Attempting to prune them before the request is sent
|
paulb@221 | 101 | fails with a function like the following:
|
paulb@221 | 102 |
|
paulb@221 | 103 | function fixValue(fieldValue) {
|
paulb@221 | 104 | if (fieldValue.length == 0) {
|
paulb@221 | 105 | return fieldValue;
|
paulb@221 | 106 | } else if (fieldValue[fieldValue.length - 1] == '\0') {
|
paulb@221 | 107 | return fieldValue.substr(0, fieldValue.length - 1);
|
paulb@221 | 108 | } else {
|
paulb@221 | 109 | return fieldValue;
|
paulb@221 | 110 | }
|
paulb@221 | 111 | }
|
paulb@221 | 112 |
|
paulb@221 | 113 | This may be because it is the entire message that is terminated with the null
|
paulb@221 | 114 | character, and that this happens only upon sending the message. Consequently,
|
paulb@221 | 115 | some frameworks (notably mod_python) do not support in-page functionality when
|
paulb@221 | 116 | used from Konqueror.
|
paulb@207 | 117 |
|
paulb@104 | 118 | Various browsers (eg. Mozilla/Firefox, Konqueror) will not allow the
|
paulb@185 | 119 | XMLHttpRequest in-page updates to function unless the URL used in the
|
paulb@185 | 120 | requestUpdate JavaScript function is compatible with the URL at which the
|
paulb@185 | 121 | browser finds the application. Currently, relative URLs are in use to avoid
|
paulb@185 | 122 | this issue of compatibility, but should an absolute URL be deduced using the
|
paulb@185 | 123 | WebStack API and then used, it may be possible that the values returned by
|
paulb@185 | 124 | that API do not match the actual addresses entered into the address bar of the
|
paulb@185 | 125 | browser.
|
paulb@28 | 126 |
|
paulb@104 | 127 | To check the behaviour of the applications, it is possible to view the
|
paulb@104 | 128 | document source of the pages served by applications and to verify that the
|
paulb@185 | 129 | URLs mentioned in the JavaScript function calls (to 'requestUpdate') either be
|
paulb@185 | 130 | a relative link or involve a URL similar to that which appears in the
|
paulb@185 | 131 | browser's address bar. In some environments, the use of 'localhost' addresses
|
paulb@185 | 132 | often confuses the browser and server; one workaround is to use real host
|
paulb@185 | 133 | names or addresses instead of 'localhost'.
|
paulb@155 | 134 |
|
paulb@166 | 135 | Choosing an element-path:
|
paulb@166 | 136 |
|
paulb@166 | 137 | When specifying the "context" of the in-page update, one must imagine which
|
paulb@166 | 138 | element the template fragment should operate within. If the template:id
|
paulb@166 | 139 | attribute marks a particular section, then the element-path should be a path
|
paulb@166 | 140 | to the applicable context element for that section in the complete template
|
paulb@166 | 141 | document. Note that if a template:element attribute appears on the same
|
paulb@166 | 142 | element as the template:id attribute then the element-path should refer to the
|
paulb@166 | 143 | element specified in the template:element attribute.
|
paulb@166 | 144 |
|
paulb@166 | 145 | Choosing where to put template:attribute, template:id and id:
|
paulb@166 | 146 |
|
paulb@166 | 147 | When specifying the extent of a template fragment, one must be sure not to put
|
paulb@166 | 148 | the template:id attribute on the same element as a template:attribute
|
paulb@166 | 149 | annotation; otherwise, the generated code will be improperly extracted as a
|
paulb@166 | 150 | fragment producing two versions of the element - one for when the specified
|
paulb@166 | 151 | attribute is present, and one for when it is not present. Generally,
|
paulb@166 | 152 | template:id and id can be placed on the same node, however.
|
paulb@173 | 153 |
|
paulb@173 | 154 | Stable element ordering and element-path:
|
paulb@173 | 155 |
|
paulb@173 | 156 | Within the element-path, the numbering of the elements will start at 1.
|
paulb@173 | 157 | Therefore it is vital to choose a region of the form data structure with the
|
paulb@173 | 158 | element-path which is isolated from surrounding elements whose positions would
|
paulb@173 | 159 | otherwise be dependent on a stable ordering of elements, and whose processing
|
paulb@173 | 160 | would be disrupted if some new elements suddenly appeared claiming the same
|
paulb@173 | 161 | positions in the document. For example:
|
paulb@173 | 162 |
|
paulb@173 | 163 | <item value=""> .../item$1/value
|
paulb@173 | 164 | <type value=""/> .../item$1/type$1/value
|
paulb@173 | 165 | <comment value=""/> .../item$1/comment$2/value
|
paulb@173 | 166 | </item>
|
paulb@173 | 167 |
|
paulb@173 | 168 | In-page update...
|
paulb@173 | 169 |
|
paulb@173 | 170 | <comment value=""/> .../item$1/comment$1/value
|
paulb@173 | 171 |
|
paulb@173 | 172 | Notes on XSL
|
paulb@173 | 173 | ------------
|
paulb@173 | 174 |
|
paulb@173 | 175 | libxslt seems to be quite liberal on the definition of runtime parameters, in
|
paulb@173 | 176 | that there is no apparent need to explicitly declare the corresponding global
|
paulb@173 | 177 | variables in stylesheets. Whilst this is nice, we may eventually need to
|
paulb@173 | 178 | detect such variables and add them in the preparation process.
|
paulb@184 | 179 |
|
paulb@184 | 180 | Release Procedures
|
paulb@184 | 181 | ------------------
|
paulb@184 | 182 |
|
paulb@201 | 183 | Update the XSLTools/__init__.py and XSLForms/__init__.py __version__
|
paulb@201 | 184 | attributes.
|
paulb@184 | 185 | Change the version number and package filename/directory in the documentation.
|
paulb@184 | 186 | Change code examples in the documentation if appropriate.
|
paulb@184 | 187 | Update the release notes (see above).
|
paulb@184 | 188 | Check the setup.py file and ensure that all package directories are mentioned.
|
paulb@207 | 189 | Check the release information in the PKG-INFO file and in the package
|
paulb@207 | 190 | changelog (and other files).
|
paulb@184 | 191 | Tag, export.
|
paulb@184 | 192 | Generate the API documentation.
|
paulb@184 | 193 | Remove generated .pyc files: rm `find . -name "*.pyc"`
|
paulb@184 | 194 | Archive, upload.
|
paulb@184 | 195 | Upload the introductory documentation.
|
paulb@184 | 196 | Update PyPI, PythonInfo Wiki, Vaults of Parnassus entries.
|
paulb@184 | 197 |
|
paulb@184 | 198 | Generating the API Documentation
|
paulb@184 | 199 | --------------------------------
|
paulb@184 | 200 |
|
paulb@184 | 201 | In order to prepare the API documentation, it is necessary to generate some
|
paulb@184 | 202 | Web pages from the Python source code. For this, the epydoc application must
|
paulb@231 | 203 | be available on your system. Then, inside the distribution directory, run the
|
paulb@184 | 204 | apidocs.sh tool script as follows:
|
paulb@184 | 205 |
|
paulb@184 | 206 | ./tools/apidocs.sh
|
paulb@184 | 207 |
|
paulb@184 | 208 | Some warnings may be generated by the script, but the result should be a new
|
paulb@231 | 209 | apidocs directory within the distribution directory.
|
paulb@218 | 210 |
|
paulb@218 | 211 | Making Packages
|
paulb@218 | 212 | ---------------
|
paulb@218 | 213 |
|
paulb@312 | 214 | To make Debian-based packages:
|
paulb@218 | 215 |
|
paulb@312 | 216 | 1. Create new package directories under packages if necessary.
|
paulb@230 | 217 | 2. Make a symbolic link in the distribution's root directory to keep the
|
paulb@230 | 218 | Debian tools happy:
|
paulb@218 | 219 |
|
paulb@312 | 220 | ln -s packages/ubuntu-hoary/python2.4-xsltools/debian/
|
paulb@218 | 221 |
|
paulb@230 | 222 | 3. Run the package builder:
|
paulb@218 | 223 |
|
paulb@230 | 224 | dpkg-buildpackage -rfakeroot
|
paulb@218 | 225 |
|
paulb@230 | 226 | 4. Locate and tidy up the packages in the parent directory of the
|
paulb@230 | 227 | distribution's root directory.
|