# HG changeset patch # User paulb # Date 1103656996 0 # Node ID 91b1fcfbd22075549c4e87f60d5c81c3d8114bfb # Parent 5276d66fb29bc0db26e7ab051acd4e8cc40b99d7 [project @ 2004-12-21 19:23:16 by paulb] Added a Constants module for field name notation details used by Fields and the extension functions in Output. Introduced a new extension function, "field-name", which works correctly with elements transformed from attributes (eg. those which can have a range of values) as well as with normal attribute references. diff -r 5276d66fb29b -r 91b1fcfbd220 XSLForms/Constants.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XSLForms/Constants.py Tue Dec 21 19:23:16 2004 +0000 @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +"Constants for XSLForms." + +path_separator = "/" +pair_separator = "#" +selector_indicator = "=" + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 5276d66fb29b -r 91b1fcfbd220 XSLForms/Fields.py --- a/XSLForms/Fields.py Tue Dec 21 00:46:33 2004 +0000 +++ b/XSLForms/Fields.py Tue Dec 21 19:23:16 2004 +0000 @@ -27,6 +27,7 @@ _action_add_animal=/zoo#1/cage#2 """ +import Constants import libxml2dom from xml.dom import EMPTY_NAMESPACE @@ -40,10 +41,6 @@ instance documents. """ - _path_separator = "/" - _pair_separator = "#" - _selector_indicator = "=" - def __init__(self, encoding="utf-8", values_are_lists=0): """ @@ -69,7 +66,7 @@ # Ignore selectors. - if field.find(self._selector_indicator) != -1: + if field.find(Constants.selector_indicator) != -1: continue model_name, components = self._get_model_name_and_components(field) @@ -96,7 +93,7 @@ # Traverse the components within the instance. for component in components: - t = component.split(self._pair_separator) + t = component.split(Constants.pair_separator) if len(t) == 1: node.setAttributeNS(EMPTY_NAMESPACE, t[0], value) break @@ -123,7 +120,7 @@ # Process selectors only. - selector_components = field.split(self._selector_indicator) + selector_components = field.split(Constants.selector_indicator) if len(selector_components) < 2: continue @@ -132,7 +129,7 @@ # but the separator really should not exist in the path. selector_name = selector_components[0] - path = self._selector_indicator.join(selector_components[1:]) + path = Constants.selector_indicator.join(selector_components[1:]) model_name, components = self._get_model_name_and_components(path) if model_name is None: @@ -149,7 +146,7 @@ # selected. for component in components: - t = component.split(self._pair_separator) + t = component.split(Constants.pair_separator) if len(t) == 1: # Select attribute. @@ -210,7 +207,7 @@ # Example: /name1#n1/name2#n2/name3 # Expected: ['', 'name1#n1', 'name2#n2', 'name3'] - components = field.split(self._path_separator) + components = field.split(Constants.path_separator) if len(components) < 2: return None, None @@ -218,7 +215,7 @@ # specification. # Expected: ['name1', 'n1'] - model_name_and_index = components[1].split(self._pair_separator) + model_name_and_index = components[1].split(Constants.pair_separator) if len(model_name_and_index) != 2: return None, None diff -r 5276d66fb29b -r 91b1fcfbd220 XSLForms/Output.py --- a/XSLForms/Output.py Tue Dec 21 00:46:33 2004 +0000 +++ b/XSLForms/Output.py Tue Dec 21 19:23:16 2004 +0000 @@ -4,6 +4,7 @@ XSL-based form templating. """ +import Constants import libxslt """ @@ -15,12 +16,22 @@ libxml2.registerErrorHandler(quiet, None) """ -def path_to_node(node, name): +def path_to_node(node, attribute_ref, name): """ - Generate an XSLForms path to the given 'node', using the given 'name' to - complete the path if an attribute reference is required (otherwise 'name' - will be None). + Generate an XSLForms path to the given 'node', producing an attribute + reference if 'attribute_ref' is true; for example: + + /package#1/discriminators#5/discriminator#1/category + + Otherwise an element reference is produced; for example: + + /package#1/discriminators#5/discriminator#1 + + Use the given 'name' to complete the path if an attribute reference is + required (and if a genuine attribute is found at the context node - + otherwise 'name' will be None and the context node will be treated like an + attribute). """ l = [] @@ -28,24 +39,30 @@ if node.type == "attribute": node = node.parent # Manually insert the attribute name if defined. - if name is not None: - l.insert(0, name) - l.insert(0, "/") + if attribute_ref: + if name is not None: + l.insert(0, name) + l.insert(0, Constants.path_separator) + else: + l.insert(0, node.name) + l.insert(0, Constants.path_separator) + node = node.parent # Element references. while node is not None and node.type != "document_xml": l.insert(0, str(int(node.xpathEval("count(preceding-sibling::*) + 1")))) - l.insert(0, "#") + l.insert(0, Constants.pair_separator) l.insert(0, node.name) - l.insert(0, "/") + l.insert(0, Constants.path_separator) node = node.parent return "".join(l) -def this_position(context): +def path_to_context(context, attribute_ref): """ As a libxslt extension function, return a string containing the XSLForms path to the 'context' node, using the special "this-name" variable to - complete the path if an attribute reference is required. + complete the path if an attribute reference is required (as indicated by + 'attribute_ref' being set to true). """ pctxt = libxslt.xpathParserContext(_obj=context) @@ -57,8 +74,15 @@ name = name_var[0].content else: name = None - return path_to_node(node, name) + return path_to_node(node, attribute_ref, name) + +def this_position(context): + return path_to_context(context, 0) + +def field_name(context): + return path_to_context(context, 1) libxslt.registerExtModuleFunction("this-position", "http://www.boddie.org.uk/ns/xmltools/template", this_position) +libxslt.registerExtModuleFunction("field-name", "http://www.boddie.org.uk/ns/xmltools/template", field_name) # vim: tabstop=4 expandtab shiftwidth=4