# HG changeset patch # User paulb # Date 1104086828 0 # Node ID b0c2af5ce181a26daa7aec60b94db69828e170af # Parent 4076e5437a9cdf8f8baf377dbda9f2bb96e01238 [project @ 2004-12-26 18:47:08 by paulb] Added multivalued field support using multiple elements in the output document, each with an attribute containing one of the values. diff -r 4076e5437a9c -r b0c2af5ce181 XSLForms/Fields.py --- a/XSLForms/Fields.py Thu Dec 23 15:07:53 2004 +0000 +++ b/XSLForms/Fields.py Sun Dec 26 18:47:08 2004 +0000 @@ -1,11 +1,6 @@ #!/usr/bin/env python """ -NOTE: Add support for multiple values from fields, perhaps using -NOTE: the following notation: -NOTE: -NOTE: /package#1/categories#1/category#n/value - Classes which process field collections, producing instance documents. Each field entry consists of a field name mapped to a string value, where the field name may have the following @@ -25,6 +20,11 @@ /zoo#1/cage#2/name /zoo#1/funding#3/contributor#1/name +Where multiple values can be collected for a given field, the +following notation is employed: + + /package#1/categories#1/category##value + Some fields may contain the "=" string. This string is reserved and all text following it is meant to specify a path into a particular document. For example: @@ -106,14 +106,35 @@ elif len(t) == 2: - # Convert from one-based indexing (the position() function) - # to zero-based indexing. + # Convert from one-based indexing (the position() + # function) to zero-based indexing. name, index = t[0], int(t[1]) - 1 if index < 0: break node = self._enter_element(node, name, index) + elif len(t) == 3 and t[1] == "": + + # Multivalued fields. + + if not self.values_are_lists: + values = [value] + else: + values = value + + name = t[0] + for index in range(0, len(values)): + subnode = self._enter_element(node, name, index) + subvalue = values[index] + + # Convert the value to Unicode if necessary. + + if type(subvalue) == type(""): + subvalue = unicode(subvalue, encoding=self.encoding) + + subnode.setAttributeNS(EMPTY_NAMESPACE, t[2], subvalue) + def complete_selectors(self, selectors, fields, documents): """ @@ -307,7 +328,8 @@ ("/zoo#1/cage#2/animal#2/property#2/value", "high"), ("/zoo#1/funding#3/type", "private"), ("/zoo#1/funding#3/contributor#1/name", "Animal Corporation"), - ("/zoo#1/funding#3/contributor#1/amount", "543210.987") + ("/zoo#1/funding#3/contributor#1/amount", "543210.987"), + ("/zoo#1/funding#3/contributor#1/industry##type", "animals") ] import time diff -r 4076e5437a9c -r b0c2af5ce181 XSLForms/Output.py --- a/XSLForms/Output.py Thu Dec 23 15:07:53 2004 +0000 +++ b/XSLForms/Output.py Sun Dec 26 18:47:08 2004 +0000 @@ -16,7 +16,7 @@ libxml2.registerErrorHandler(quiet, None) """ -def path_to_node(node, attribute_ref, name): +def path_to_node(node, attribute_ref, name, multivalue=0): """ Generate an XSLForms path to the given 'node', producing an attribute @@ -32,6 +32,11 @@ 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). + + If 'multivalue' is true, produce an attribute reference using the given + 'name' of the following form: + + /package#1/categories#1/category##name """ l = [] @@ -40,9 +45,16 @@ node = node.parent # Manually insert the attribute name if defined. if attribute_ref: + # A real attribute is referenced. if name is not None: l.insert(0, name) + if multivalue: + l.insert(0, Constants.pair_separator) + l.insert(0, Constants.pair_separator) + l.insert(0, node.name) + node = node.parent l.insert(0, Constants.path_separator) + # Otherwise, treat the element name as an attribute name. else: l.insert(0, node.name) l.insert(0, Constants.path_separator) @@ -56,13 +68,15 @@ node = node.parent return "".join(l) -def path_to_context(context, attribute_ref): +def path_to_context(context, attribute_ref, multivalue_name=None): """ 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 (as indicated by - 'attribute_ref' being set to true). + 'attribute_ref' being set to true). If 'multivalue_name' is set, produce a + reference to a multivalued field using the given string as the attribute + name. """ pctxt = libxslt.xpathParserContext(_obj=context) @@ -70,11 +84,16 @@ node = context.contextNode() transform_context = context.transformContext() name_var = transform_context.variableLookup("this-name", None) - if name_var is not None: + if multivalue_name is not None: + name = multivalue_name + multivalue = 1 + elif name_var is not None: name = name_var[0].content + multivalue = 0 else: name = None - return path_to_node(node, attribute_ref, name) + multivalue = 0 + return path_to_node(node, attribute_ref, name, multivalue) def this_position(context): return path_to_context(context, 0) @@ -82,7 +101,11 @@ def field_name(context): return path_to_context(context, 1) +def multi_field_name(context, multivalue_name): + return path_to_context(context, 1, multivalue_name) + 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) +libxslt.registerExtModuleFunction("multi-field-name", "http://www.boddie.org.uk/ns/xmltools/template", multi_field_name) # vim: tabstop=4 expandtab shiftwidth=4