XSLTools

XSLForms/Resources/WebResources.py

480:1c7309b5dada
2006-01-27 paulb [project @ 2006-01-27 00:35:15 by paulb] Changed the preparation of fragment stylesheets to use the original template instead of the complete generated output stylesheet.
     1 #!/usr/bin/env python     2      3 """     4 Resources for use with WebStack.     5      6 Copyright (C) 2005 Paul Boddie <paul@boddie.org.uk>     7      8 This library is free software; you can redistribute it and/or     9 modify it under the terms of the GNU Lesser General Public    10 License as published by the Free Software Foundation; either    11 version 2.1 of the License, or (at your option) any later version.    12     13 This library is distributed in the hope that it will be useful,    14 but WITHOUT ANY WARRANTY; without even the implied warranty of    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    16 Lesser General Public License for more details.    17     18 You should have received a copy of the GNU Lesser General Public    19 License along with this library; if not, write to the Free Software    20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA    21 """    22     23 import WebStack.Generic    24 import XSLForms.Fields    25 import XSLForms.Prepare    26 import XSLForms.Output    27 import XSLForms.Resources.Common    28 from XSLTools import XSLOutput    29 import os    30     31 class XSLFormsResource(XSLForms.Resources.Common.CommonResource):    32     33     """    34     A generic XSLForms resource for use with WebStack.    35     36     When overriding this class, define the following attributes appropriately:    37     38       * template_resources    - a dictionary mapping output identifiers to    39                                 (template_filename, output_filename) tuples,    40                                 indicating the template and stylesheet filenames    41                                 to be employed    42     43       * in_page_resources     - a dictionary mapping fragment identifiers to    44                                 (output_filename, node_identifier) tuples,    45                                 indicating the stylesheet filename to be    46                                 employed, along with the node identifier used in    47                                 the original template and output documents to    48                                 mark a region of those documents as the fragment    49                                 to be updated upon "in-page" requests    50     51       * init_resources        - a dictionary mapping initialiser/input    52                                 identifiers to (template_filename,    53                                 input_filename) tuples, indicating the template    54                                 and initialiser/input stylesheet filenames to be    55                                 employed    56                                     57       * transform_resources   - a dictionary mapping transform identifiers to    58                                 lists of stylesheet filenames for use with the    59                                 transformation methods    60     61       * document_resources    - a dictionary mapping document identifiers to    62                                 single filenames for use as source documents or    63                                 as references with the transformation methods    64     65       * resource_dir          - the absolute path of the directory in which    66                                 stylesheet resources are to reside    67     68     All filenames shall be simple leafnames for files residing in the resource's    69     special resource directory 'resource_dir'.    70     71     The following attributes may also be specified:    72     73       * path_encoding         - the assumed encoding of characters in request    74                                 paths    75     76       * encoding              - the assumed encoding of characters in request    77                                 bodies    78     """    79     80     path_encoding = "utf-8"    81     encoding = "utf-8"    82     template_resources = {}    83     in_page_resources = {}    84     init_resources = {}    85     transform_resources = {}    86     87     def clean_parameters(self, parameters):    88     89         """    90         Workaround stray zero value characters from Konqueror in XMLHttpRequest    91         communications.    92         """    93     94         for name, values in parameters.items():    95             new_values = []    96             for value in values:    97                 if value.endswith("\x00"):    98                     new_values.append(value[:-1])    99                 else:   100                     new_values.append(value)   101             parameters[name] = new_values   102    103     def prepare_output(self, output_identifier):   104    105         """   106         Prepare the output stylesheets using the given 'output_identifier' to   107         indicate which templates and stylesheets are to be employed in the   108         production of output from the resource.   109    110         The 'output_identifier' is used as a key to the 'template_resources'   111         dictionary attribute.   112    113         Return the full path to the output stylesheet for use with 'send_output'   114         or 'get_result'.   115         """   116    117         template_filename, output_filename = self.template_resources[output_identifier]   118         output_path = os.path.abspath(os.path.join(self.resource_dir, output_filename))   119         template_path = os.path.abspath(os.path.join(self.resource_dir, template_filename))   120         XSLForms.Prepare.ensure_stylesheet(template_path, output_path)   121         return output_path   122    123     def prepare_fragment(self, output_identifier, fragment_identifier):   124    125         """   126         Prepare the output stylesheets for the given 'output_identifier' and   127         'fragment_identifier', indicating which templates and stylesheets are to   128         be employed in the production of output from the resource.   129    130         The 'output_identifier' is used as a key to the 'template_resources'   131         dictionary attribute; the 'fragment_identifier' is used as a key to the   132         'in_page_resources' dictionary attribute.   133    134         Return the full path to the output stylesheet for use with 'send_output'   135         or 'get_result'.   136         """   137    138         template_filename, output_filename = self.template_resources[output_identifier]   139         template_path = os.path.abspath(os.path.join(self.resource_dir, template_filename))   140         fragment_filename, node_identifier = self.in_page_resources[fragment_identifier]   141         fragment_path = os.path.abspath(os.path.join(self.resource_dir, fragment_filename))   142         XSLForms.Prepare.ensure_stylesheet_fragment(template_path, fragment_path, node_identifier)   143         return fragment_path   144    145     def prepare_parameters(self, parameters):   146    147         """   148         Prepare the stylesheet parameters from the given request 'parameters'.   149         This is most useful when preparing fragments for in-page update output.   150         """   151    152         element_path = parameters.get("element-path", [""])[0]   153         if element_path:   154             return {"element-path" : element_path}   155         else:   156             return {}   157    158     def send_output(self, trans, stylesheet_filenames, document, stylesheet_parameters=None,   159         stylesheet_expressions=None, references=None):   160    161         """   162         Send the output from the resource to the user employing the transaction   163         'trans', stylesheets having the given 'stylesheet_filenames', the   164         'document' upon which the output will be based, the optional parameters   165         as defined in the 'stylesheet_parameters' dictionary, the optional   166         expressions are defined in the 'stylesheet_expressions' dictionary, and   167         the optional 'references' to external documents.   168         """   169    170         # Sanity check for the filenames list.   171    172         if isinstance(stylesheet_filenames, str) or isinstance(stylesheet_filenames, unicode):   173             raise ValueError, stylesheet_filenames   174    175         proc = XSLOutput.Processor(stylesheet_filenames, parameters=stylesheet_parameters,   176             expressions=stylesheet_expressions, references=references)   177         proc.send_output(trans.get_response_stream(), trans.get_response_stream_encoding(),   178             document)   179    180     def get_result(self, stylesheet_filenames, document, stylesheet_parameters=None,   181         stylesheet_expressions=None, references=None):   182    183         """   184         Get the result of applying a transformation using stylesheets with the   185         given 'stylesheet_filenames', the 'document' upon which the result will   186         be based, the optional parameters as defined in the   187         'stylesheet_parameters' dictionary, the optional parameters as defined   188         in the 'stylesheet_parameters' dictionaryand the optional 'references'   189         to external documents.   190         """   191    192         # Sanity check for the filenames list.   193    194         if isinstance(stylesheet_filenames, str) or isinstance(stylesheet_filenames, unicode):   195             raise ValueError, stylesheet_filenames   196    197         proc = XSLOutput.Processor(stylesheet_filenames, parameters=stylesheet_parameters,   198             expressions=stylesheet_expressions, references=references)   199         return proc.get_result(document)   200    201     def prepare_initialiser(self, input_identifier, init_enumerations=1):   202    203         """   204         Prepare an initialiser/input transformation using the given   205         'input_identifier'. The optional 'init_enumerations' (defaulting to   206         true) may be used to indicate whether enumerations are to be initialised   207         from external documents.   208    209         Return the full path to the input stylesheet for use with 'send_output'   210         or 'get_result'.   211         """   212    213         template_filename, input_filename = self.init_resources[input_identifier]   214         input_path = os.path.abspath(os.path.join(self.resource_dir, input_filename))   215         template_path = os.path.abspath(os.path.join(self.resource_dir, template_filename))   216         XSLForms.Prepare.ensure_input_stylesheet(template_path, input_path, init_enumerations)   217         return input_path   218    219     def prepare_transform(self, transform_identifier):   220    221         """   222         Prepare a transformation using the given 'transform_identifier'.   223    224         Return a list of full paths to the output stylesheets for use with   225         'send_output' or 'get_result'.   226         """   227    228         filenames = self.transform_resources[transform_identifier]   229    230         # Sanity check for the filenames list.   231    232         if isinstance(filenames, str) or isinstance(filenames, unicode):   233             raise ValueError, filenames   234    235         paths = []   236         for filename in filenames:   237             paths.append(os.path.abspath(os.path.join(self.resource_dir, filename)))   238         return paths   239    240     def get_in_page_resource(self, trans):   241    242         """   243         Return the in-page resource being referred to in the given transaction   244         'trans'.   245         """   246    247         return trans.get_path_info(self.path_encoding).split("/")[-1]   248    249     def respond(self, trans):   250    251         """   252         Respond to the request described by the given transaction 'trans'.   253         """   254    255         # Only obtain field information according to the stated method.   256    257         method = trans.get_request_method()   258         in_page_resource = self.get_in_page_resource(trans)   259    260         # Handle typical request methods, processing request information.   261    262         if method == "GET":   263    264             # Get the fields from the request path (URL).   265             # NOTE: The encoding is actually redundant since WebStack produces   266             # NOTE: Unicode values.   267    268             form = XSLForms.Fields.Form(encoding=self.path_encoding, values_are_lists=1)   269             parameters = trans.get_fields_from_path()   270             form.set_parameters(parameters)   271    272         elif method == "POST":   273    274             # Get the fields from the request body.   275             # NOTE: The encoding is actually redundant since WebStack produces   276             # NOTE: Unicode values.   277    278             form = XSLForms.Fields.Form(encoding=self.encoding, values_are_lists=1)   279             parameters = trans.get_fields_from_body(self.encoding)   280    281             # NOTE: Konqueror workaround.   282             self.clean_parameters(parameters)   283    284             form.set_parameters(parameters)   285    286         else:   287    288             # Initialise empty container.   289    290             form = XSLForms.Fields.Form(encoding=self.encoding, values_are_lists=1)   291    292         # Call an overridden method with the processed request information.   293    294         self.respond_to_form(trans, form)   295    296     def respond_to_form(self, trans, form):   297    298         """   299         Respond to the request described by the given transaction 'trans', using   300         the given 'form' object to conveniently retrieve field (request   301         parameter) information and structured form information (as DOM-style XML   302         documents).   303         """   304    305         trans.set_response_code(500)   306         trans.set_content_type(WebStack.Generic.ContentType("text/plain"))   307         out = trans.get_response_stream()   308         out.write("Resource not fully defined to respond.")   309         raise WebStack.Generic.EndOfResponse   310    311 # vim: tabstop=4 expandtab shiftwidth=4