Set background colour when hiding/showing.
[dom-editor.git] / Dome / xslt.py
bloba90ae65c0cd1e1468bd14a136c0fa341ac0279ab
1 from constants import XSLT_NS
2 from xml.dom import Node
4 from Ft.Xml.Xslt.StylesheetReader import StylesheetReader
5 from Ft.Xml.Xslt.StylesheetTree import XsltElement, XsltText
6 from Ft.Xml.Xslt.LiteralElement import LiteralElement
7 from Ft.Xml.Xslt.ApplyTemplatesElement import ApplyTemplatesElement
8 from Program import Program, Op, Block
10 def import_sheet(doc):
11 print "Import!", doc
13 root = Program('XSLT')
15 # The root program puts the mark on the Result node and the cursor on the Source.
16 # It then runs the program for the default mode. There is one program for each mode, and
17 # it acts as a dispatcher. It finds a template which matches the cursor node and runs
18 # the program for that template.
20 op = add(root.code.start, 'do_search', '/xslt/Result')
21 op = add(op, 'mark_selection')
22 op = add(op, 'do_search', '/xslt/Source')
23 op = add(op, 'play', 'XSLT/Default mode')
25 # This program copies a text node to the output
26 prog = Program('DefaultText')
27 root.add_sub(prog)
28 op = add(prog.code.start, 'yank')
29 op = add(op, 'mark_switch')
30 op = add(op, 'put_as_child_end')
31 op = add(op, 'move_left')
32 op = add(op, 'mark_switch')
34 # To start with, the cursor is on the source document node and
35 # the mark is on the result document node.
37 # The mode program is called with:
38 # => Cursor = context node
39 # Mark = result parent (append children here)
40 # <= Cursor is undefined
41 # Mark is unchanged
43 reader = StylesheetReader()
44 sheet = reader.fromDocument(doc)
46 global s
47 s = sheet
48 print sheet
50 # sheet.matchTemplates is { mode -> { type -> { (ns, name) -> [match] for elements
51 # { [match] otherwise
53 # Each match is (pattern, axis_type, TemplateElement)
55 # The list of matches is sorted; use the first that matches. Multiple lookups
56 # may be required (eg, lookup 'html' then None (for 'node()' and '*')).
57 # Patterns like 'text()|comment()' are broken down into two match elements.
59 # XXX: Could have two modes with the same name but different namespaces...
61 i = 1
63 for mode in sheet.matchTemplates.keys():
64 if mode:
65 mode_name = 'Mode:' + mode[1]
66 else:
67 mode_name = 'Default mode'
68 prog = Program(mode_name)
69 root.add_sub(prog)
70 tests = prog.code.start
71 print "Mode", mode
72 types = sheet.matchTemplates[mode]
73 loose_ends = []
74 for type in types.keys():
75 if type == Node.ELEMENT_NODE:
76 templates = types[type].values()
77 else:
78 templates = [types[type]]
79 for tl in templates:
80 for t in tl:
81 pattern = `t[0]`
82 name = pattern.replace('/', '%')
83 temp = Program(`i` + '-' + name)
84 op = add(temp.code.start, 'mark_switch')
85 make_template(op, t[2])
86 i += 1
87 prog.add_sub(temp)
89 if pattern.startswith('/'):
90 if pattern == '/':
91 pattern = ''
92 pattern = '/xslt/Source' + pattern # XXX: Hack
93 tests = add(tests, 'fail_if', pattern)
94 op = Op(action = ['play', temp.get_path()])
95 tests.link_to(op, 'fail')
96 loose_ends.append(op)
97 # Now add the built-in rules
99 print "Tidy", loose_ends
101 tests = add(tests, 'fail_if', 'text()')
102 op = Op(action = ['play', 'XSLT/DefaultText'])
103 tests.link_to(op, 'fail')
105 tests = add(tests, 'do_global', '*')
106 tests = add(tests, 'map', prog.get_path())
107 tests = add(tests, 'mark_switch')
108 tests = add(tests, 'mark_switch')
109 [ op.link_to(tests, 'next') for op in loose_ends ]
111 root.modified = 0
112 return root
114 def add(op, *action):
115 new = Op(action = action)
116 op.link_to(new, 'next')
117 return new
119 # A template is instantiated by running its program.
121 # => Cursor = result parent (append here)
122 # Mark = context node
124 # <= Cursor is undefined
125 # Mark is unchanged
127 # Add the instructions to instantiate this template to 'op'.
128 def make_template(op, temp):
129 for child in temp.children:
130 if isinstance(child, XsltText):
131 print "Text node", child.data
132 op = add(op, 'add_node', 'et', child.data)
133 op = add(op, 'move_left')
135 elif isinstance(child, LiteralElement):
136 print "Element", child._output_qname
137 op = add(op, 'add_node', 'ee', child._output_qname)
138 op = make_template(op, child)
139 op = add(op, 'move_left')
140 elif isinstance(child, ApplyTemplatesElement):
141 block = Block(op.parent)
142 block.toggle_restore()
143 sub = block.start
145 if child._select:
146 match = `child._select`
147 else:
148 match = '*|text()'
150 print "MATCH:", match
151 sub = add(sub, 'mark_switch')
152 sub = add(sub, 'do_global', match)
153 sub = add(sub, 'map', 'XSLT/Default mode')
154 sub = add(sub, 'mark_switch')
156 op.link_to(block, 'next')
157 op = block
158 else:
159 print "Unknown template type", child, "(%s)" % child.__class__
160 return op