1 #!/usr/bin/env python 2 3 """ 4 XSL-based form templating. 5 """ 6 7 import libxslt 8 9 """ 10 import libxml2 11 12 def quiet(context, s): 13 pass 14 15 libxml2.registerErrorHandler(quiet, None) 16 """ 17 18 def path_to_node(node, name): 19 20 """ 21 Generate an XSLForms path to the given 'node', using the given 'name' to 22 complete the path if an attribute reference is required (otherwise 'name' 23 will be None). 24 """ 25 26 l = [] 27 # Skip attribute reference. 28 if node.type == "attribute": 29 node = node.parent 30 # Manually insert the attribute name if defined. 31 if name is not None: 32 l.insert(0, name) 33 l.insert(0, "/") 34 # Element references. 35 while node is not None and node.type != "document_xml": 36 l.insert(0, str(int(node.xpathEval("count(preceding-sibling::*) + 1")))) 37 l.insert(0, "#") 38 l.insert(0, node.name) 39 l.insert(0, "/") 40 node = node.parent 41 return "".join(l) 42 43 def this_position(context): 44 45 """ 46 As a libxslt extension function, return a string containing the XSLForms 47 path to the 'context' node, using the special "this-name" variable to 48 complete the path if an attribute reference is required. 49 """ 50 51 pctxt = libxslt.xpathParserContext(_obj=context) 52 context = pctxt.context() 53 node = context.contextNode() 54 transform_context = context.transformContext() 55 name_var = transform_context.variableLookup("this-name", None) 56 if name_var is not None: 57 name = name_var[0].content 58 else: 59 name = None 60 return path_to_node(node, name) 61 62 libxslt.registerExtModuleFunction("this-position", "http://www.boddie.org.uk/ns/xmltools/template", this_position) 63 64 # vim: tabstop=4 expandtab shiftwidth=4