# HG changeset patch # User Paul Boddie # Date 1223759462 -7200 # Node ID a333f8d849e82c6350e61774742713563b2887a8 # Parent 2ee0853b91649ff50d31ca48796d818e83dcd1cc Added the template:nodes function which uses recent libxml2dom fixes (0.5) to provide general references to elements and attributes, although new attributes (ones which are to be created) still require the template:other-attributes or template:new-attribute functions. diff -r 2ee0853b9164 -r a333f8d849e8 README.txt --- a/README.txt Fri Jun 20 23:27:43 2008 +0000 +++ b/README.txt Sat Oct 11 23:11:02 2008 +0200 @@ -44,7 +44,7 @@ Packages Release Information -------- ------------------- -libxml2dom 0.4.3 (0.4.6 recommended for XInclude support) +libxml2dom 0.5 libxml2 and libxslt Some combinations may not be reliable! Tested with libxml2 2.6.17 and libxslt 1.1.12 Tested with libxml2 2.6.27 and libxslt 1.1.20 diff -r 2ee0853b9164 -r a333f8d849e8 XSLForms/Output.py --- a/XSLForms/Output.py Fri Jun 20 23:27:43 2008 +0000 +++ b/XSLForms/Output.py Sat Oct 11 23:11:02 2008 +0200 @@ -3,7 +3,7 @@ """ XSL-based form templating. -Copyright (C) 2005, 2007 Paul Boddie +Copyright (C) 2005, 2007, 2008 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free @@ -34,7 +34,7 @@ libxml2_encoding = "utf-8" -def path_to_node(node, attribute_ref, name, multivalue=0): +def path_to_node(node, attribute_ref=None, name=None, multivalue=0): """ Generate an XSLForms path to the given 'node', producing an attribute @@ -63,12 +63,27 @@ """ l = [] - # Skip attribute reference. + + # Skip attribute references. + # Where a node reference has been requested, initialise the name and + # attribute reference settings. + if node.nodeType == node.ATTRIBUTE_NODE: + if name is None: + name = node.localName + if attribute_ref is None: + attribute_ref = 1 node = node.parentNode + else: + if attribute_ref is None: + attribute_ref = 0 + # 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: @@ -76,13 +91,17 @@ l.insert(0, node.nodeName) node = node.parentNode l.insert(0, Constants.path_separator) + # Otherwise, treat the element name as an attribute name. # NOTE: Not sure how useful this is. + else: l.insert(0, node.nodeName) l.insert(0, Constants.path_separator) node = node.parentNode + # Otherwise insert any multivalue references (eg. list-attribute). + elif multivalue: element_name, attribute_name = name l.insert(0, attribute_name) @@ -91,12 +110,14 @@ l.insert(0, Constants.path_separator) # Element references. + while node is not None and node.nodeType != node.DOCUMENT_NODE: l.insert(0, str(int(node.xpath("count(preceding-sibling::*) + 1")))) l.insert(0, Constants.pair_separator) l.insert(0, node.nodeName) l.insert(0, Constants.path_separator) node = node.parentNode + return "".join(l) def path_to_context(context, attribute_ref, multivalue_name=None): @@ -234,9 +255,9 @@ #print "other_attributes" attribute_name = unicode(attribute_name, libxml2_encoding) - # NOTE: Cannot directly reference attributes in the nodes list because - # NOTE: libxml2dom does not yet support parent element discovery on - # NOTE: attributes. + # NOTE: Could not directly reference attributes in the nodes list because + # NOTE: libxml2dom did not yet support parent element discovery on + # NOTE: attributes. The nodes function below remedies this. names = [] for node in nodes: name = path_to_node(libxml2dom.Node(node), 1, attribute_name, 0) @@ -245,6 +266,23 @@ r = ",".join(names) return r.encode(libxml2_encoding) +def nodes(context, nodes): + + """ + Exposed as {template:nodes(nodes)}. + + Provides a reference to 'nodes' in the form data structure, described using + an XPath expression in the template. + """ + + names = [] + for node in nodes: + name = path_to_node(libxml2dom.Node(node)) + if name not in names: + names.append(name) + r = ",".join(names) + return r.encode(libxml2_encoding) + def child_element(context, element_name, position, node_paths): """ @@ -493,6 +531,7 @@ libxsltmod.xsltRegisterExtModuleFunction("child-element", "http://www.boddie.org.uk/ns/xmltools/template", child_element) libxsltmod.xsltRegisterExtModuleFunction("child-attribute", "http://www.boddie.org.uk/ns/xmltools/template", child_attribute) libxsltmod.xsltRegisterExtModuleFunction("selector-name", "http://www.boddie.org.uk/ns/xmltools/template", selector_name) +libxsltmod.xsltRegisterExtModuleFunction("nodes", "http://www.boddie.org.uk/ns/xmltools/template", nodes) # New names.