2004-12-20 | paulb | raw files shortlog changelog graph | [project @ 2004-12-20 00:30:39 by paulb] Initial revision | initial |
XSLForms/Fields.py (file) XSLForms/Output.py (file) XSLForms/Prepare.py (file) XSLForms/XSL/Prepare.xsl (file) XSLForms/__init__.py (file) XSLOutput.py (file) examples/Common/PEP241/Resources/pep241_error.xml (file) examples/Common/PEP241/Resources/pep241_template.xhtml (file) examples/Common/PEP241/Resources/styles.css (file) scripts/output.py (file) scripts/prepare.py (file) |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/XSLForms/Fields.py Mon Dec 20 00:30:39 2004 +0000 1.3 @@ -0,0 +1,332 @@ 1.4 +#!/usr/bin/env python 1.5 + 1.6 +""" 1.7 +Classes which process field collections, producing instance 1.8 +documents. Each field entry consists of a field name mapped 1.9 +to a string value, where the field name may have the following 1.10 +formats: 1.11 + 1.12 + /name1#n1/name2 1.13 + /name1#n1/name2#n2/name3 1.14 + /name1#n1/name2#n2/name3#n3/name4 1.15 + ... 1.16 + 1.17 +The indexes n1, n2, n3, ... indicate the position of elements 1.18 +(starting from 1) in the entire element list, whose elements 1.19 +may have different names. For example: 1.20 + 1.21 + /zoo#1/name 1.22 + /zoo#1/cage#1:name 1.23 + /zoo#1/cage#2:name 1.24 + /zoo#1/funding#3/contributor#1/name 1.25 + 1.26 +Some fields may contain the "=" string. This string is 1.27 +reserved and all text following it is meant to specify a path 1.28 +into a particular document. For example: 1.29 + 1.30 + _action_add_animal=/zoo#1/cage#2 1.31 +""" 1.32 + 1.33 +import libxml2dom 1.34 +from xml.dom import EMPTY_NAMESPACE 1.35 + 1.36 +class FieldsError(Exception): 1.37 + pass 1.38 + 1.39 +class Fields: 1.40 + 1.41 + """ 1.42 + A class which converts fields in the documented form to XML 1.43 + instance documents. 1.44 + """ 1.45 + 1.46 + _path_separator = "/" 1.47 + _pair_separator = "#" 1.48 + _selector_indicator = "=" 1.49 + 1.50 + def __init__(self, encoding="utf-8"): 1.51 + 1.52 + """ 1.53 + Initialise the fields processor with the given 'encoding', 1.54 + which is optional and which only applies to field data in 1.55 + Python string form (and not Unicode objects). 1.56 + """ 1.57 + 1.58 + self.encoding = encoding 1.59 + 1.60 + def complete_documents(self, documents, fields): 1.61 + 1.62 + """ 1.63 + Complete the given 'documents' using the 'fields' items list. 1.64 + """ 1.65 + 1.66 + for field, value in fields: 1.67 + 1.68 + # Ignore selectors. 1.69 + 1.70 + if field.find(self._selector_indicator) != -1: 1.71 + continue 1.72 + 1.73 + model_name, components = self._get_model_name_and_components(field) 1.74 + if model_name is None: 1.75 + continue 1.76 + 1.77 + # Convert the value to Unicode if necessary. 1.78 + 1.79 + if type(value) == type(""): 1.80 + value = unicode(value, encoding=self.encoding) 1.81 + 1.82 + # Get a new instance document if none has been made for the 1.83 + # model. 1.84 + 1.85 + if not documents.has_key(model_name): 1.86 + documents[model_name] = self._new_instance(model_name) 1.87 + node = documents[model_name] 1.88 + 1.89 + # Traverse the components within the instance. 1.90 + 1.91 + for component in components: 1.92 + t = component.split(self._pair_separator) 1.93 + if len(t) == 1: 1.94 + node.setAttributeNS(EMPTY_NAMESPACE, t[0], value) 1.95 + break 1.96 + 1.97 + elif len(t) == 2: 1.98 + 1.99 + # Convert from one-based indexing (the position() function) 1.100 + # to zero-based indexing. 1.101 + 1.102 + name, index = t[0], int(t[1]) - 1 1.103 + if index < 0: 1.104 + break 1.105 + node = self._enter_element(node, name, index) 1.106 + 1.107 + def complete_selectors(self, selectors, fields, documents): 1.108 + 1.109 + """ 1.110 + Fill in the given 'selectors' dictionary using the given 1.111 + 'fields' so that it contains mappings from selector names to 1.112 + parts of the specified 'documents'. 1.113 + """ 1.114 + 1.115 + for field, value in fields: 1.116 + 1.117 + # Process selectors only. 1.118 + 1.119 + selector_components = field.split(self._selector_indicator) 1.120 + if len(selector_components) < 2: 1.121 + continue 1.122 + 1.123 + # Get the selector name and path. 1.124 + # Note that the joining of the components uses the separator, 1.125 + # but the separator really should not exist in the path. 1.126 + 1.127 + selector_name = selector_components[0] 1.128 + path = self._selector_indicator.join(selector_components[1:]) 1.129 + 1.130 + model_name, components = self._get_model_name_and_components(path) 1.131 + if model_name is None: 1.132 + continue 1.133 + 1.134 + # Go to the instance element. 1.135 + 1.136 + if not documents.has_key(model_name) or documents[model_name] is None: 1.137 + continue 1.138 + 1.139 + node = documents[model_name] 1.140 + 1.141 + # Traverse the path to find the part of the document to be 1.142 + # selected. 1.143 + 1.144 + for component in components: 1.145 + t = component.split(self._pair_separator) 1.146 + if len(t) == 1: 1.147 + 1.148 + # Select attribute. 1.149 + 1.150 + node = node.getAttributeNodeNS(EMPTY_NAMESPACE, t[0]) 1.151 + break 1.152 + 1.153 + elif len(t) == 2: 1.154 + 1.155 + # Convert from one-based indexing (the position() function) 1.156 + # to zero-based indexing. 1.157 + 1.158 + name, index = t[0], int(t[1]) - 1 1.159 + if index < 0: 1.160 + break 1.161 + 1.162 + # NOTE: Controversial creation of potentially non-existent 1.163 + # NOTE: nodes. 1.164 + 1.165 + node = self._enter_element(node, name, index) 1.166 + 1.167 + if not selectors.has_key(selector_name): 1.168 + selectors[selector_name] = [] 1.169 + selectors[selector_name].append(node) 1.170 + 1.171 + def _enter_element(self, node, name, index): 1.172 + 1.173 + """ 1.174 + From 'node' enter the element with the given 'name' at the 1.175 + given 'index' position amongst the child elements. Create 1.176 + missing child elements if necessary. 1.177 + """ 1.178 + 1.179 + self._ensure_elements(node, index) 1.180 + 1.181 + elements = node.xpath("*") 1.182 + if elements[index].localName == "placeholder": 1.183 + new_node = node.ownerDocument.createElementNS(EMPTY_NAMESPACE, name) 1.184 + node.replaceChild(new_node, elements[index]) 1.185 + else: 1.186 + new_node = elements[index] 1.187 + if new_node.localName != name: 1.188 + raise FieldsError, (new_node.localName, name, elements, index) 1.189 + 1.190 + # Enter the newly-created element. 1.191 + 1.192 + return new_node 1.193 + 1.194 + def _get_model_name_and_components(self, field): 1.195 + 1.196 + """ 1.197 + From 'field', return the model name and components which 1.198 + describe the path within the instance document associated 1.199 + with that model. 1.200 + """ 1.201 + 1.202 + # Get the components of the field name. 1.203 + # Example: /name1#n1/name2#n2/name3 1.204 + # Expected: ['', 'name1#n1', 'name2#n2', 'name3'] 1.205 + 1.206 + components = field.split(self._path_separator) 1.207 + if len(components) < 2: 1.208 + return None, None 1.209 + 1.210 + # Extract the model name from the top-level element 1.211 + # specification. 1.212 + # Expected: ['name1', 'n1'] 1.213 + 1.214 + model_name_and_index = components[1].split(self._pair_separator) 1.215 + if len(model_name_and_index) != 2: 1.216 + return None, None 1.217 + 1.218 + # Expected: 'name1', ['', 'name1#n1', 'name2#n2', 'name3'] 1.219 + 1.220 + return model_name_and_index[0], components[1:] 1.221 + 1.222 + def _ensure_elements(self, document, index): 1.223 + 1.224 + """ 1.225 + In the given 'document', extend the child elements list 1.226 + so that a node can be stored at the given 'index'. 1.227 + """ 1.228 + 1.229 + elements = document.xpath("*") 1.230 + i = len(elements) 1.231 + while i <= index: 1.232 + new_node = document.ownerDocument.createElementNS(EMPTY_NAMESPACE, "placeholder") 1.233 + document.appendChild(new_node) 1.234 + i += 1 1.235 + 1.236 + def make_documents(self, fields): 1.237 + 1.238 + """ 1.239 + Make a dictionary mapping model names to new documents prepared 1.240 + from the given 'fields' dictionary. 1.241 + """ 1.242 + 1.243 + documents = {} 1.244 + self.complete_documents(documents, fields) 1.245 + 1.246 + # Fix the dictionary to return the actual document root. 1.247 + 1.248 + for model_name, instance_root in documents.items(): 1.249 + documents[model_name] = instance_root 1.250 + return documents 1.251 + 1.252 + def get_selectors(self, fields, documents): 1.253 + 1.254 + """ 1.255 + Get a dictionary containing a mapping of selector names to 1.256 + selected parts of the given 'documents'. 1.257 + """ 1.258 + 1.259 + selectors = {} 1.260 + self.complete_selectors(selectors, fields, documents) 1.261 + return selectors 1.262 + 1.263 + def _new_instance(self, name): 1.264 + 1.265 + "Return an instance root of the given 'name' in a new document." 1.266 + 1.267 + return libxml2dom.createDocument(EMPTY_NAMESPACE, name, None) 1.268 + 1.269 +if __name__ == "__main__": 1.270 + 1.271 + d = [ 1.272 + ("_action_update", "Some value"), 1.273 + ("_action_delete=/zoo#1/cage#2", "Some value"), 1.274 + ("/actions#1/update#1/selected", "Some value"), # Not actually used in output documents or input. 1.275 + ("/zoo#1/name", "The Zoo זרו"), 1.276 + ("/zoo#1/cage#1/name", "reptiles"), 1.277 + ("/zoo#1/cage#1/capacity", "5"), 1.278 + ("/zoo#1/cage#1/animal#1/name", "Monty"), 1.279 + ("/zoo#1/cage#1/animal#1/species#1/name", "Python"), 1.280 + ("/zoo#1/cage#1/animal#1/property#2/name", "texture"), 1.281 + ("/zoo#1/cage#1/animal#1/property#2/value", "scaled"), 1.282 + ("/zoo#1/cage#1/animal#1/property#3/name", "length"), 1.283 + ("/zoo#1/cage#1/animal#1/property#3/value", "5m"), 1.284 + ("/zoo#1/cage#1/animal#2/name", "Vincent"), 1.285 + ("/zoo#1/cage#1/animal#2/species#1/name", "Lizard"), 1.286 + ("/zoo#1/cage#1/animal#2/property#2/name", "colour"), 1.287 + ("/zoo#1/cage#1/animal#2/property#2/value", "variable"), 1.288 + ("/zoo#1/cage#1/animal#2/property#3/name", "length"), 1.289 + ("/zoo#1/cage#1/animal#2/property#3/value", "1m"), 1.290 + ("/zoo#1/cage#2/name", "mammals"), 1.291 + ("/zoo#1/cage#2/capacity", "25"), 1.292 + ("/zoo#1/cage#2/animal#1/name", "Simon"), 1.293 + ("/zoo#1/cage#2/animal#1/species#1/name", "Giraffe"), 1.294 + ("/zoo#1/cage#2/animal#2/name", "Leonard"), 1.295 + ("/zoo#1/cage#2/animal#2/species#1/name", "Lion"), 1.296 + ("/zoo#1/cage#2/animal#2/property#2/name", "danger"), 1.297 + ("/zoo#1/cage#2/animal#2/property#2/value", "high"), 1.298 + ("/zoo#1/funding#3/type", "private"), 1.299 + ("/zoo#1/funding#3/contributor#1/name", "Animal Corporation"), 1.300 + ("/zoo#1/funding#3/contributor#1/amount", "543210.987") 1.301 + ] 1.302 + 1.303 + import time 1.304 + import sys, cmdsyntax 1.305 + 1.306 + # Find the documents. 1.307 + 1.308 + syntax = cmdsyntax.Syntax(""" 1.309 + --plain-output=OUTPUT_FILE 1.310 + --instance-name=NAME 1.311 + """) 1.312 + 1.313 + syntax_matches = syntax.get_args(sys.argv[1:]) 1.314 + 1.315 + try: 1.316 + args = syntax_matches[0] 1.317 + except IndexError: 1.318 + print syntax.syntax 1.319 + sys.exit(1) 1.320 + 1.321 + # Create an object to interpret the test data. 1.322 + 1.323 + fields = Fields("iso-8859-1") 1.324 + 1.325 + t = time.time() 1.326 + documents = fields.make_documents(d) 1.327 + print "Building time", time.time() - t 1.328 + 1.329 + t = time.time() 1.330 + libxml2dom.toStream(documents[args["instance-name"]], stream=open(args["plain-output"], "wb"), encoding="utf-8") 1.331 + print "Prettyprinting time", time.time() - t 1.332 + 1.333 + print "Selectors", repr(fields.get_selectors(d, documents)) 1.334 + 1.335 +# vim: tabstop=4 expandtab shiftwidth=4
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/XSLForms/Output.py Mon Dec 20 00:30:39 2004 +0000 2.3 @@ -0,0 +1,50 @@ 2.4 +#!/usr/bin/env python 2.5 + 2.6 +""" 2.7 +XSL-based form templating. 2.8 +""" 2.9 + 2.10 +import libxslt 2.11 + 2.12 +""" 2.13 +import libxml2 2.14 + 2.15 +def quiet(context, s): 2.16 + pass 2.17 + 2.18 +libxml2.registerErrorHandler(quiet, None) 2.19 +""" 2.20 + 2.21 +def path_to_node(node): 2.22 + 2.23 + "Generate an XSLForms path to the given 'node'." 2.24 + 2.25 + l = [] 2.26 + # Attribute reference. 2.27 + l.insert(0, node.name) 2.28 + l.insert(0, "/") 2.29 + node = node.parent 2.30 + # Element references. 2.31 + while node is not None and node.type != "document_xml": 2.32 + l.insert(0, str(int(node.xpathEval("count(preceding-sibling::*) + 1")))) 2.33 + l.insert(0, "#") 2.34 + l.insert(0, node.name) 2.35 + l.insert(0, "/") 2.36 + node = node.parent 2.37 + return "".join(l) 2.38 + 2.39 +def this_position(context): 2.40 + 2.41 + """ 2.42 + As a libxslt extension function, return a string containing the XSLForms 2.43 + path to the 'context' node. 2.44 + """ 2.45 + 2.46 + pctxt = libxslt.xpathParserContext(_obj=context) 2.47 + context = pctxt.context() 2.48 + node = context.contextNode() 2.49 + return path_to_node(node) 2.50 + 2.51 +libxslt.registerExtModuleFunction("this-position", "http://www.boddie.org.uk/ns/xmltools/template", this_position) 2.52 + 2.53 +# vim: tabstop=4 expandtab shiftwidth=4
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/XSLForms/Prepare.py Mon Dec 20 00:30:39 2004 +0000 3.3 @@ -0,0 +1,19 @@ 3.4 +#!/usr/bin/env python 3.5 + 3.6 +""" 3.7 +Preparation of templating stylesheets. 3.8 +""" 3.9 + 3.10 +import XSLOutput 3.11 +import libxml2dom 3.12 +import os 3.13 + 3.14 +resource_dir = os.path.join(os.path.split(__file__)[0], "XSL") 3.15 + 3.16 +def make_stylesheet(template_name, output_name, stylesheet_name="Prepare.xsl", encoding="utf-8"): 3.17 + global resource_dir 3.18 + proc = XSLOutput.Processor([os.path.join(resource_dir, stylesheet_name)]) 3.19 + template = libxml2dom.parse(template_name) 3.20 + proc.send_output(open(output_name, "wb"), encoding, template) 3.21 + 3.22 +# vim: tabstop=4 expandtab shiftwidth=4
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/XSLForms/XSL/Prepare.xsl Mon Dec 20 00:30:39 2004 +0000 4.3 @@ -0,0 +1,141 @@ 4.4 +<?xml version="1.0"?> 4.5 +<xsl:stylesheet version="1.0" 4.6 + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4.7 + xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias" 4.8 + xmlns:template="http://www.boddie.org.uk/ns/xmltools/template"> 4.9 + 4.10 + <xsl:output indent="yes"/> 4.11 + <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/> 4.12 + <xsl:variable name="template-expr">http://www.boddie.org.uk/ns/xmltools/template-expr</xsl:variable> 4.13 + 4.14 + <!-- Match the document itself. --> 4.15 + 4.16 + <xsl:template match="/"> 4.17 + <axsl:stylesheet version="1.0"> 4.18 + <axsl:template match="/"> 4.19 + 4.20 + <!-- Include the remaining attributes. --> 4.21 + <xsl:apply-templates select="@*"/> 4.22 + 4.23 + <!-- Process the elements. --> 4.24 + <xsl:apply-templates select="*"/> 4.25 + 4.26 + </axsl:template> 4.27 + </axsl:stylesheet> 4.28 + </xsl:template> 4.29 + 4.30 + 4.31 + 4.32 + <!-- Match element references. --> 4.33 + 4.34 + <xsl:template match="*[@template:element]"> 4.35 + <xsl:call-template name="enter-element"> 4.36 + <xsl:with-param name="other-elements" select="@template:element"/> 4.37 + </xsl:call-template> 4.38 + </xsl:template> 4.39 + 4.40 + <xsl:template name="enter-element"> 4.41 + <xsl:param name="other-elements"/> 4.42 + <xsl:variable name="first-element" select="substring-before($other-elements, ',')"/> 4.43 + <xsl:variable name="remaining-elements" select="substring-after($other-elements, ',')"/> 4.44 + <xsl:choose> 4.45 + <xsl:when test="$first-element = ''"> 4.46 + <xsl:call-template name="next-element"> 4.47 + <xsl:with-param name="first-element" select="$other-elements"/> 4.48 + </xsl:call-template> 4.49 + </xsl:when> 4.50 + <xsl:otherwise> 4.51 + <xsl:call-template name="next-element"> 4.52 + <xsl:with-param name="first-element" select="$first-element"/> 4.53 + <xsl:with-param name="remaining-elements" select="$remaining-elements"/> 4.54 + </xsl:call-template> 4.55 + </xsl:otherwise> 4.56 + </xsl:choose> 4.57 + </xsl:template> 4.58 + 4.59 + <xsl:template name="next-element"> 4.60 + <xsl:param name="first-element"/> 4.61 + <xsl:param name="remaining-elements"/> 4.62 + <axsl:for-each select="{$first-element}"> 4.63 + <xsl:choose> 4.64 + <xsl:when test="$remaining-elements = ''"> 4.65 + <xsl:call-template name="special-attributes"/> 4.66 + </xsl:when> 4.67 + <xsl:otherwise> 4.68 + <xsl:call-template name="enter-element"> 4.69 + <xsl:with-param name="other-elements" select="$remaining-elements"/> 4.70 + </xsl:call-template> 4.71 + </xsl:otherwise> 4.72 + </xsl:choose> 4.73 + </axsl:for-each> 4.74 + </xsl:template> 4.75 + 4.76 + 4.77 + 4.78 + <!-- Match special expression attributes. --> 4.79 + 4.80 + <xsl:template match="*[not(@template:element) and (@template:attribute or @template:value or @template:expr)]"> 4.81 + <xsl:call-template name="special-attributes"/> 4.82 + </xsl:template> 4.83 + 4.84 + <xsl:template name="special-attributes"> 4.85 + <xsl:choose> 4.86 + <xsl:when test="@template:effect = 'replace'"> 4.87 + <xsl:call-template name="special-values"/> 4.88 + </xsl:when> 4.89 + <xsl:otherwise> 4.90 + <xsl:copy> 4.91 + <xsl:apply-templates select="@*"/> 4.92 + <xsl:if test="@template:expr and @template:expr-attr"> 4.93 + <axsl:if test="{@template:expr}"> 4.94 + <axsl:attribute name="{@template:expr-attr}"><xsl:value-of select="@template:expr-attr"/></axsl:attribute> 4.95 + </axsl:if> 4.96 + </xsl:if> 4.97 + <xsl:call-template name="special-values"/> 4.98 + </xsl:copy> 4.99 + </xsl:otherwise> 4.100 + </xsl:choose> 4.101 + </xsl:template> 4.102 + 4.103 + <xsl:template name="special-values"> 4.104 + <xsl:choose> 4.105 + <xsl:when test="@template:attribute"> 4.106 + <axsl:for-each select="@{@template:attribute}"> 4.107 + <xsl:call-template name="special-value"/> 4.108 + </axsl:for-each> 4.109 + </xsl:when> 4.110 + <xsl:otherwise> 4.111 + <xsl:call-template name="special-value"/> 4.112 + </xsl:otherwise> 4.113 + </xsl:choose> 4.114 + </xsl:template> 4.115 + 4.116 + <xsl:template name="special-value"> 4.117 + <xsl:choose> 4.118 + <xsl:when test="@template:value"> 4.119 + <axsl:value-of select="{@template:value}"/> 4.120 + </xsl:when> 4.121 + <xsl:otherwise> 4.122 + <xsl:apply-templates select="node()"/> 4.123 + </xsl:otherwise> 4.124 + </xsl:choose> 4.125 + </xsl:template> 4.126 + 4.127 + 4.128 + 4.129 + <!-- Remove template elements. --> 4.130 + 4.131 + <xsl:template match="@template:element|@template:attribute|@template:value|@template:expr|@template:expr-attr|@template:effect"> 4.132 + </xsl:template> 4.133 + 4.134 + 4.135 + 4.136 + <!-- Replicate unknown elements. --> 4.137 + 4.138 + <xsl:template match="@*|node()"> 4.139 + <xsl:copy> 4.140 + <xsl:apply-templates select="@*|node()"/> 4.141 + </xsl:copy> 4.142 + </xsl:template> 4.143 + 4.144 +</xsl:stylesheet>
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/XSLOutput.py Mon Dec 20 00:30:39 2004 +0000 6.3 @@ -0,0 +1,102 @@ 6.4 +#!/usr/bin/env python 6.5 + 6.6 +""" 6.7 +XSL output classes and functions. 6.8 +""" 6.9 + 6.10 +# NOTE: Make this use other implementations, too. 6.11 + 6.12 +import libxslt 6.13 +import libxml2dom 6.14 + 6.15 +class OutputError(Exception): 6.16 + pass 6.17 + 6.18 +class Processor: 6.19 + 6.20 + """ 6.21 + A handler which can prepare output for an XMLTools2 template. 6.22 + """ 6.23 + 6.24 + def __init__(self, filenames, references=None): 6.25 + 6.26 + """ 6.27 + Initialise the handler with the 'filenames' of stylesheets producing the 6.28 + final output, a 'references' dictionary indicating related stylesheets. 6.29 + """ 6.30 + 6.31 + self.references = references or {} 6.32 + 6.33 + # Remember the stylesheet documents. 6.34 + 6.35 + self.stylesheets = [] 6.36 + for filename in filenames: 6.37 + self.stylesheets.append(libxslt.parseStylesheetFile(filename)) 6.38 + 6.39 + def __del__(self): 6.40 + 6.41 + """ 6.42 + Tidy up the stylesheet documents. 6.43 + """ 6.44 + 6.45 + for stylesheet in self.stylesheets: 6.46 + stylesheet.freeStylesheet() 6.47 + 6.48 + def send_output(self, stream, encoding, document): 6.49 + 6.50 + """ 6.51 + Send output to the given 'stream' using the given output encoding for 6.52 + the given 'document'. 6.53 + """ 6.54 + 6.55 + result = self._get_result(document) 6.56 + 6.57 + if result is not None: 6.58 + # Since result is a native node, use the serialize method. 6.59 + stream.write(result.serialize(encoding)) 6.60 + result.freeDoc() 6.61 + else: 6.62 + raise OutputError, "Transformation failed." 6.63 + 6.64 + def get_result(self, document): 6.65 + 6.66 + """ 6.67 + Return a transformed document produced from the object's stylesheets and 6.68 + the given 'document'. 6.69 + """ 6.70 + 6.71 + result = self._get_result(document) 6.72 + 6.73 + if result is not None: 6.74 + return libxml2dom.Node(result) 6.75 + else: 6.76 + raise OutputError, "Transformation failed." 6.77 + 6.78 + def _get_result(self, document): 6.79 + 6.80 + """ 6.81 + Return a transformation of the given 'document'. 6.82 + """ 6.83 + 6.84 + if hasattr(document, "as_native_node"): 6.85 + document = document.as_native_node() 6.86 + 6.87 + # Transform the localised instance into the final output. 6.88 + 6.89 + parameters = {} 6.90 + for name, reference in self.references.items(): 6.91 + parameters[name.encode("utf-8")] = ("document('%s')" % reference).encode("utf-8") 6.92 + 6.93 + last_result = document 6.94 + for stylesheet in self.stylesheets: 6.95 + result = stylesheet.applyStylesheet(last_result, parameters) 6.96 + if last_result is not None: 6.97 + if last_result != document: 6.98 + last_result.freeDoc() 6.99 + last_result = result 6.100 + else: 6.101 + raise OutputError, "Transformation failed." 6.102 + 6.103 + return result 6.104 + 6.105 +# vim: tabstop=4 expandtab shiftwidth=4
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/examples/Common/PEP241/Resources/pep241_error.xml Mon Dec 20 00:30:39 2004 +0000 7.3 @@ -0,0 +1,47 @@ 7.4 +<?xml version="1.0"?> 7.5 +<package name="XMLTools2"> 7.6 + <details version="0.1" metadata-version="1.0" summary="An XML tools package for Python." description="A suite of tools which perform certain XML processing tasks, written in Python." home-page="http://www.boddie.org.uk/python/XMLTools2/" licence="GNU LGPL"/> 7.7 + <platforms> 7.8 + <platform name="Linux"/> 7.9 + <platform name="Windows"/> 7.10 + </platforms> 7.11 + <keywords> 7.12 + <keyword name="XML"/> 7.13 + <keyword name="SQL"/> 7.14 + </keywords> 7.15 + <authors> 7.16 + <author name="Paul Boddie" contact="Oslo, Norway" e-mail="paul@boddie.org.uk"/> 7.17 + <author name="The Badger" e-mail="badger@infukor.com"/> 7.18 + </authors> 7.19 + <dependencies> 7.20 + <dependency name="PyXML" version="0.7.1"/> 7.21 + </dependencies> 7.22 + <discriminators> 7.23 + <discriminator> 7.24 + <category value="Programming Language :: Python"> 7.25 + <category-enum value="Development Status :: 1 - Planning"/> 7.26 + <category-enum value="Development Status :: 2 - Pre-Alpha"/> 7.27 + <category-enum value="Development Status :: 3 - Alpha"/> 7.28 + <category-enum value="Development Status :: 4 - Beta"/> 7.29 + <category-enum value="Development Status :: 5 - Production/Stable"/> 7.30 + <category-enum value="Development Status :: 6 - Mature"/> 7.31 + <category-enum value="Development Status :: 7 - Inactive"/> 7.32 + <category-enum value="Programming Language :: Python"/> 7.33 + <category-enum value="Topic :: Text Processing :: Markup :: XML"/> 7.34 + </category> 7.35 + </discriminator> 7.36 + <discriminator> 7.37 + <category value="Topic :: Text Processing :: Markup :: XML"> 7.38 + <category-enum value="Development Status :: 1 - Planning"/> 7.39 + <category-enum value="Development Status :: 2 - Pre-Alpha"/> 7.40 + <category-enum value="Development Status :: 3 - Alpha"/> 7.41 + <category-enum value="Development Status :: 4 - Beta"/> 7.42 + <category-enum value="Development Status :: 5 - Production/Stable"/> 7.43 + <category-enum value="Development Status :: 6 - Mature"/> 7.44 + <category-enum value="Development Status :: 7 - Inactive"/> 7.45 + <category-enum value="Programming Language :: Python"/> 7.46 + <category-enum value="Topic :: Text Processing :: Markup :: XML"/> 7.47 + </category> 7.48 + </discriminator> 7.49 + </discriminators> 7.50 +</package>
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/examples/Common/PEP241/Resources/pep241_template.xhtml Mon Dec 20 00:30:39 2004 +0000 8.3 @@ -0,0 +1,184 @@ 8.4 +<?xml version="1.0" encoding="iso-8859-1"?> 8.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 8.6 + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 8.7 +<html xmlns="http://www.w3.org/1999/xhtml" 8.8 + xmlns:template="http://www.boddie.org.uk/ns/xmltools/template"> 8.9 +<head> 8.10 + <title>PEP 241 Package Registry</title> 8.11 + <meta name="generator" content="amaya 8.1a, see http://www.w3.org/Amaya/" /> 8.12 + <link xmlns:xlink="http://www.w3.org/1999/xlink" href="styles.css" 8.13 + rel="stylesheet" type="text/css" /> 8.14 +</head> 8.15 + 8.16 +<body> 8.17 +<h1>PEP 241 Package Registry</h1> 8.18 + 8.19 +<form method="get"> 8.20 + 8.21 + <table cellspacing="0" cellpadding="5" template:element="package"> 8.22 + <tbody> 8.23 + <tr> 8.24 + <th class="heading" colspan="2">Summary</th> 8.25 + </tr> 8.26 + <tr> 8.27 + <th>Package name</th> 8.28 + <td template:attribute="name"> 8.29 + <input name="{template:this-position()}" type="text" value="{string(.)}"/> 8.30 + </td> 8.31 + </tr> 8.32 + </tbody> 8.33 + <tbody template:element="details"> 8.34 + <tr> 8.35 + <th>Package version</th> 8.36 + <td template:attribute="version"><span template:value="string(.)">0.2</span></td> 8.37 + </tr> 8.38 + <tr> 8.39 + <th>Summary</th> 8.40 + <td template:attribute="summary"><span template:value="string(.)" template:effect="replace">An XML-based 8.41 + Web forms processing package.</span></td> 8.42 + </tr> 8.43 + <tr> 8.44 + <th>Description</th> 8.45 + <td template:attribute="description" template:value="string(.)">Insert 8.46 + longer description here!</td> 8.47 + </tr> 8.48 + <tr template:element="error"> 8.49 + <th></th> 8.50 + <td template:attribute="size" class="error">Only {size} characters can be used in a 8.51 + description.</td> 8.52 + </tr> 8.53 + <tr> 8.54 + <th>Home page</th> 8.55 + <td template:attribute="home-page" template:value="string(.)">http://www.boddie.org.uk/python/XMLForms2/index.html</td> 8.56 + </tr> 8.57 + <tr> 8.58 + <th>Licence</th> 8.59 + <td template:attribute="licence" template:value="string(.)">LGPL</td> 8.60 + </tr> 8.61 + </tbody> 8.62 + <tbody template:element="discriminators"> 8.63 + <tr> 8.64 + <th colspan="2" class="heading">Discriminators</th> 8.65 + </tr> 8.66 + <tr template:element="discriminator"> 8.67 + <th>Discriminator</th> 8.68 + <td template:element="category"> 8.69 + <select name="{template:this-position()}"> 8.70 + <option template:element="category-enum" value="{@value}" 8.71 + template:expr-attr="selected" template:expr="@value = ../@value" template:value="@value"/> 8.72 + </select> 8.73 + <input type="submit" value="Remove!" name="_action_remove_discriminator={template:this-position()}" /></td> 8.74 + </tr> 8.75 + <tr> 8.76 + <th></th> 8.77 + <td><input type="submit" value="Add discriminator!" name="_action_add_discriminator={template:this-position()}" /></td> 8.78 + </tr> 8.79 + </tbody> 8.80 + <tbody template:element="platforms"> 8.81 + <tr> 8.82 + <th colspan="2" class="heading">Platforms</th> 8.83 + </tr> 8.84 + <tr template:element="platform"> 8.85 + <th>Platform name</th> 8.86 + <td><span template:attribute="name" template:value=".">Linux (with more listed below)</span> 8.87 + <input type="submit" value="Remove!" name="_action_remove_platform={template:this-position()}" /></td> 8.88 + </tr> 8.89 + <tr> 8.90 + <th></th> 8.91 + <td> 8.92 + <input type="submit" value="Add platform!" name="_action_add_platform={template:this-position()}" /></td> 8.93 + </tr> 8.94 + </tbody> 8.95 + <tbody template:element="supported-platforms"> 8.96 + <tr> 8.97 + <th colspan="2" class="heading">Supported platforms</th> 8.98 + </tr> 8.99 + <tr template:element="supported-platform"> 8.100 + <th>Platform name</th> 8.101 + <td><span template:attribute="name" template:value="string(.)">Linux (with more listed below)</span> 8.102 + <input type="submit" value="Remove!" name="_action_remove_supported_platform={template:this-position()}" /></td> 8.103 + </tr> 8.104 + <tr> 8.105 + <th></th> 8.106 + <td> 8.107 + <input type="submit" value="Add platform!" name="_action_add_supported_platform={template:this-position()}" /></td> 8.108 + </tr> 8.109 + </tbody> 8.110 + <tbody template:element="keywords"> 8.111 + <tr> 8.112 + <th colspan="2" class="heading">Keywords</th> 8.113 + </tr> 8.114 + <tr template:element="keyword"> 8.115 + <th>Keyword</th> 8.116 + <td><span template:attribute="name" template:value="string(.)">Web programming</span> 8.117 + <input type="submit" value="Remove!" name="_action_remove_keyword={template:this-position()}" /></td> 8.118 + </tr> 8.119 + <tr> 8.120 + <th></th> 8.121 + <td><input type="submit" value="Add keyword!" name="_action_add_keyword={template:this-position()}" /></td> 8.122 + </tr> 8.123 + </tbody> 8.124 + <tbody> 8.125 + <tr> 8.126 + <th colspan="2" class="heading">Authors</th> 8.127 + </tr> 8.128 + </tbody> 8.129 + <tbody template:element="authors,author"> 8.130 + <tr> 8.131 + <th>Author name</th> 8.132 + <td><span template:attribute="name" template:value="string(.)">Paul Boddie</span> 8.133 + <input type="submit" value="Remove!" name="_action_remove_author={template:this-position()}" /></td> 8.134 + </tr> 8.135 + <tr> 8.136 + <th>Author contact</th> 8.137 + <td template:attribute="contact" template:value="string(.)">Oslo, Norway</td> 8.138 + </tr> 8.139 + <tr> 8.140 + <th>Author e-mail</th> 8.141 + <td template:attribute="e-mail" template:value="string(.)">paul@boddie.org.uk</td> 8.142 + </tr> 8.143 + </tbody> 8.144 + <tbody> 8.145 + <tr> 8.146 + <th></th> 8.147 + <td><input type="submit" value="Add author!" name="_action_add_author={template:this-position()}" /></td> 8.148 + </tr> 8.149 + </tbody> 8.150 + <tbody> 8.151 + <tr> 8.152 + <th colspan="2" class="heading">Dependencies</th> 8.153 + </tr> 8.154 + </tbody> 8.155 + <tbody template:element="dependencies,dependency"> 8.156 + <tr> 8.157 + <th>Package name</th> 8.158 + <td><span template:attribute="name" template:value="string(.)">XMLTools2</span> 8.159 + <input type="submit" value="Remove!" name="_action_remove_dependency={template:this-position()}" /></td> 8.160 + </tr> 8.161 + <tr> 8.162 + <th>Package version</th> 8.163 + <td template:attribute="version" template:value="string(.)">0.2</td> 8.164 + </tr> 8.165 + </tbody> 8.166 + <tbody> 8.167 + <tr> 8.168 + <th></th> 8.169 + <td> 8.170 + <input type="submit" value="Add dependency!" name="_action_add_dependency={template:this-position()}" /></td> 8.171 + </tr> 8.172 + </tbody> 8.173 + <tbody> 8.174 + <tr> 8.175 + <th colspan="2" class="heading">Actions</th> 8.176 + </tr> 8.177 + <tr> 8.178 + <th></th> 8.179 + <td> 8.180 + <input type="submit" value="Update!" name="_action_update" /> 8.181 + <input type="submit" value="Finish!" name="_action_finish" /></td> 8.182 + </tr> 8.183 + </tbody> 8.184 + </table> 8.185 +</form> 8.186 +</body> 8.187 +</html>
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/examples/Common/PEP241/Resources/styles.css Mon Dec 20 00:30:39 2004 +0000 9.3 @@ -0,0 +1,11 @@ 9.4 +BODY { 9.5 +background-color: white; 9.6 +} 9.7 + 9.8 +.heading { 9.9 +background-color: silver; 9.10 +} 9.11 + 9.12 +.error { 9.13 +color: red; 9.14 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/scripts/output.py Mon Dec 20 00:30:39 2004 +0000 10.3 @@ -0,0 +1,24 @@ 10.4 +#!/usr/bin/env python 10.5 + 10.6 +"Prepare a templating stylesheet." 10.7 + 10.8 +import XSLForms.Output 10.9 +import XSLOutput 10.10 +import libxml2dom 10.11 +import sys 10.12 + 10.13 +if __name__ == "__main__": 10.14 + try: 10.15 + input_xml = sys.argv[1] 10.16 + trans_xsl = sys.argv[2] 10.17 + output_xml = sys.argv[3] 10.18 + except IndexError: 10.19 + print "Please specify an input filename, a template filename and an output filename." 10.20 + print "For example:" 10.21 + print "output.py input.xml output.xsl output.xhtml" 10.22 + sys.exit(1) 10.23 + 10.24 + proc = XSLOutput.Processor([trans_xsl]) 10.25 + proc.send_output(open(output_xml, "wb"), "utf-8", libxml2dom.parse(input_xml)) 10.26 + 10.27 +# vim: tabstop=4 expandtab shiftwidth=4
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/scripts/prepare.py Mon Dec 20 00:30:39 2004 +0000 11.3 @@ -0,0 +1,20 @@ 11.4 +#!/usr/bin/env python 11.5 + 11.6 +"Prepare a templating stylesheet." 11.7 + 11.8 +import XSLForms.Prepare 11.9 +import sys 11.10 + 11.11 +if __name__ == "__main__": 11.12 + try: 11.13 + input_xml = sys.argv[1] 11.14 + output_xml = sys.argv[2] 11.15 + except IndexError: 11.16 + print "Please specify a template and an output filename." 11.17 + print "For example:" 11.18 + print "prepare.py template.xhtml output.xsl" 11.19 + sys.exit(1) 11.20 + 11.21 + XSLForms.Prepare.make_stylesheet(input_xml, output_xml) 11.22 + 11.23 +# vim: tabstop=4 expandtab shiftwidth=4