1.1 --- a/XSLForms/Output.py Fri Jun 20 23:27:43 2008 +0000
1.2 +++ b/XSLForms/Output.py Sat Oct 11 23:11:02 2008 +0200
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 XSL-based form templating.
1.6
1.7 -Copyright (C) 2005, 2007 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2005, 2007, 2008 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU Lesser General Public License as published by the Free
1.12 @@ -34,7 +34,7 @@
1.13
1.14 libxml2_encoding = "utf-8"
1.15
1.16 -def path_to_node(node, attribute_ref, name, multivalue=0):
1.17 +def path_to_node(node, attribute_ref=None, name=None, multivalue=0):
1.18
1.19 """
1.20 Generate an XSLForms path to the given 'node', producing an attribute
1.21 @@ -63,12 +63,27 @@
1.22 """
1.23
1.24 l = []
1.25 - # Skip attribute reference.
1.26 +
1.27 + # Skip attribute references.
1.28 + # Where a node reference has been requested, initialise the name and
1.29 + # attribute reference settings.
1.30 +
1.31 if node.nodeType == node.ATTRIBUTE_NODE:
1.32 + if name is None:
1.33 + name = node.localName
1.34 + if attribute_ref is None:
1.35 + attribute_ref = 1
1.36 node = node.parentNode
1.37 + else:
1.38 + if attribute_ref is None:
1.39 + attribute_ref = 0
1.40 +
1.41 # Manually insert the attribute name if defined.
1.42 +
1.43 if attribute_ref:
1.44 +
1.45 # A real attribute is referenced.
1.46 +
1.47 if name is not None:
1.48 l.insert(0, name)
1.49 if multivalue:
1.50 @@ -76,13 +91,17 @@
1.51 l.insert(0, node.nodeName)
1.52 node = node.parentNode
1.53 l.insert(0, Constants.path_separator)
1.54 +
1.55 # Otherwise, treat the element name as an attribute name.
1.56 # NOTE: Not sure how useful this is.
1.57 +
1.58 else:
1.59 l.insert(0, node.nodeName)
1.60 l.insert(0, Constants.path_separator)
1.61 node = node.parentNode
1.62 +
1.63 # Otherwise insert any multivalue references (eg. list-attribute).
1.64 +
1.65 elif multivalue:
1.66 element_name, attribute_name = name
1.67 l.insert(0, attribute_name)
1.68 @@ -91,12 +110,14 @@
1.69 l.insert(0, Constants.path_separator)
1.70
1.71 # Element references.
1.72 +
1.73 while node is not None and node.nodeType != node.DOCUMENT_NODE:
1.74 l.insert(0, str(int(node.xpath("count(preceding-sibling::*) + 1"))))
1.75 l.insert(0, Constants.pair_separator)
1.76 l.insert(0, node.nodeName)
1.77 l.insert(0, Constants.path_separator)
1.78 node = node.parentNode
1.79 +
1.80 return "".join(l)
1.81
1.82 def path_to_context(context, attribute_ref, multivalue_name=None):
1.83 @@ -234,9 +255,9 @@
1.84
1.85 #print "other_attributes"
1.86 attribute_name = unicode(attribute_name, libxml2_encoding)
1.87 - # NOTE: Cannot directly reference attributes in the nodes list because
1.88 - # NOTE: libxml2dom does not yet support parent element discovery on
1.89 - # NOTE: attributes.
1.90 + # NOTE: Could not directly reference attributes in the nodes list because
1.91 + # NOTE: libxml2dom did not yet support parent element discovery on
1.92 + # NOTE: attributes. The nodes function below remedies this.
1.93 names = []
1.94 for node in nodes:
1.95 name = path_to_node(libxml2dom.Node(node), 1, attribute_name, 0)
1.96 @@ -245,6 +266,23 @@
1.97 r = ",".join(names)
1.98 return r.encode(libxml2_encoding)
1.99
1.100 +def nodes(context, nodes):
1.101 +
1.102 + """
1.103 + Exposed as {template:nodes(nodes)}.
1.104 +
1.105 + Provides a reference to 'nodes' in the form data structure, described using
1.106 + an XPath expression in the template.
1.107 + """
1.108 +
1.109 + names = []
1.110 + for node in nodes:
1.111 + name = path_to_node(libxml2dom.Node(node))
1.112 + if name not in names:
1.113 + names.append(name)
1.114 + r = ",".join(names)
1.115 + return r.encode(libxml2_encoding)
1.116 +
1.117 def child_element(context, element_name, position, node_paths):
1.118
1.119 """
1.120 @@ -493,6 +531,7 @@
1.121 libxsltmod.xsltRegisterExtModuleFunction("child-element", "http://www.boddie.org.uk/ns/xmltools/template", child_element)
1.122 libxsltmod.xsltRegisterExtModuleFunction("child-attribute", "http://www.boddie.org.uk/ns/xmltools/template", child_attribute)
1.123 libxsltmod.xsltRegisterExtModuleFunction("selector-name", "http://www.boddie.org.uk/ns/xmltools/template", selector_name)
1.124 +libxsltmod.xsltRegisterExtModuleFunction("nodes", "http://www.boddie.org.uk/ns/xmltools/template", nodes)
1.125
1.126 # New names.
1.127