def import_sheet(doc): #print "Import!", doc root = Program('XSLT') # The root program puts the mark on the Result node and the cursor on the Source. # It then runs the program for the default mode. There is one program for each mode, and # it acts as a dispatcher. It finds a template which matches the cursor node and runs # the program for that template. op = add(root.code.start, 'do_search', '/xslt/Result') op = add(op, 'mark_selection') op = add(op, 'do_search', '/xslt/Source') op = add(op, 'play', 'XSLT/Default mode') # This program copies a text node to the output prog = Program('DefaultText') root.add_sub(prog) op = add(prog.code.start, 'yank') op = add(op, 'mark_switch') op = add(op, 'put_as_child_end') op = add(op, 'move_left') op = add(op, 'mark_switch') # To start with, the cursor is on the source document node and # the mark is on the result document node. # # The mode program is called with: # => Cursor = context node # Mark = result parent (append children here) # <= Cursor is undefined # Mark is unchanged reader = StylesheetReader() sheet = reader.fromDocument(doc) global s s = sheet # sheet.matchTemplates is { mode -> { type -> { (ns, name) -> [match] for elements # { [match] otherwise # # Each match is ((precedence,?), pattern, axis_type, TemplateElement) # # The list of matches is sorted; use the first that matches. Multiple lookups # may be required (eg, lookup 'html' then None (for 'node()' and '*')). # Patterns like 'text()|comment()' are broken down into two match elements. # XXX: Could have two modes with the same name but different namespaces... i = 1 for mode in sheet.matchTemplates.keys(): mode_name = mode_prog_name(mode) prog = Program(mode_name) root.add_sub(prog) tests = prog.code.start print "Mode", mode types = sheet.matchTemplates[mode] #loose_ends = [] all = [] for type in types.keys(): if type == Node.ELEMENT_NODE: templates = types[type].values()[:] else: templates = [types[type]] # templates is a list of templates for items of this type when in this mode for tl in templates: for t in tl: all.append(t) all = all[:] all.sort() all.reverse() # highest numbers first last = None for sort_key, (unused_pattern, axis_type, template) in all: pattern = `template._match` if pattern == last: continue last = pattern #print sort_key, pattern, axis_type, template name = pattern.replace('/', '%') temp = Program(`i` + '-' + name) op = add(temp.code.start, 'mark_switch') make_template(op, template) i += 1 prog.add_sub(temp) if pattern.startswith('/'): if pattern == '/': pattern = '' pattern = '/xslt/Source' + pattern # XXX: Hack tests = add(tests, 'xslt_fail_if', pattern) op = Op(action = ['play', temp.get_path()]) tests.link_to(op, 'fail') add(op, 'mark_switch') #loose_ends.append(op) # Now add the built-in rules #print "Tidy", loose_ends tests = add(tests, 'xslt_fail_if', 'text()') op = Op(action = ['play', 'XSLT/DefaultText']) tests.link_to(op, 'fail') tests = add(tests, 'do_global', '*') tests = add(tests, 'map', prog.get_path()) #tests = add(tests, 'mark_switch') #tests = add(tests, 'mark_switch') #[ op.link_to(tests, 'next') for op in loose_ends ] root.modified = 0 return root